or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

golang.org/x/term

The term package provides support functions for dealing with terminals, as commonly found on UNIX systems. It offers low-level terminal manipulation capabilities including putting terminals into raw mode, reading passwords without echo, querying terminal dimensions, and providing a VT100 terminal implementation for line-based input with readline-like functionality.

Package Information

  • Package Name: golang.org/x/term
  • Package Type: Go module
  • Language: Go
  • Installation: go get golang.org/x/term@v0.37.0

Core Imports

import "golang.org/x/term"

Basic Usage

Putting a terminal into raw mode

package main

import (
	"fmt"
	"os"
	"golang.org/x/term"
)

func main() {
	// Save the current state and put terminal in raw mode
	oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		panic(err)
	}
	defer term.Restore(int(os.Stdin.Fd()), oldState)

	// Terminal is now in raw mode
	fmt.Println("Terminal is in raw mode")
}

Reading a password

package main

import (
	"fmt"
	"os"
	"golang.org/x/term"
)

func main() {
	fmt.Print("Enter password: ")
	password, err := term.ReadPassword(int(os.Stdin.Fd()))
	if err != nil {
		panic(err)
	}
	fmt.Printf("\nPassword entered: %s\n", password)
}

Using the VT100 terminal for interactive input

package main

import (
	"fmt"
	"io"
	"os"
	"golang.org/x/term"
)

func main() {
	// Put terminal in raw mode first
	oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		panic(err)
	}
	defer term.Restore(int(os.Stdin.Fd()), oldState)

	// Create a VT100 terminal
	terminal := term.NewTerminal(os.Stdin, "> ")

	for {
		line, err := terminal.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}
		fmt.Printf("You entered: %s\n", line)
	}
}

Capabilities

Terminal Detection

Check if a file descriptor is a terminal.

func IsTerminal(fd int) bool

Parameters:

  • fd int: File descriptor to check

Returns:

  • bool: Returns true if the given file descriptor is a terminal, false otherwise

Raw Mode Management

Put a terminal into raw mode and restore it later.

func MakeRaw(fd int) (*State, error)

Puts the terminal connected to the given file descriptor into raw mode and returns the previous state of the terminal so that it can be restored.

Parameters:

  • fd int: File descriptor of the terminal to put into raw mode

Returns:

  • *State: Previous terminal state that can be used to restore the terminal
  • error: Error if the operation fails
func Restore(fd int, oldState *State) error

Restores the terminal connected to the given file descriptor to a previous state.

Parameters:

  • fd int: File descriptor of the terminal to restore
  • oldState *State: Previous state to restore (typically from MakeRaw or GetState)

Returns:

  • error: Error if the operation fails

Terminal State Management

Get and manage terminal state.

func GetState(fd int) (*State, error)

Returns the current state of a terminal which may be useful to restore the terminal after a signal.

Parameters:

  • fd int: File descriptor of the terminal

Returns:

  • *State: Current terminal state
  • error: Error if the operation fails

Terminal Dimensions

Query terminal size.

func GetSize(fd int) (width, height int, err error)

Returns the visible dimensions of the given terminal. These dimensions don't include any scrollback buffer height.

Parameters:

  • fd int: File descriptor of the terminal

Returns:

  • width int: Terminal width in columns
  • height int: Terminal height in rows
  • err error: Error if the operation fails

Password Reading

Read passwords without local echo.

func ReadPassword(fd int) ([]byte, error)

Reads a line of input from a terminal without local echo. This is commonly used for inputting passwords and other sensitive data. The slice returned does not include the \n.

Parameters:

  • fd int: File descriptor of the terminal

Returns:

  • []byte: Password data without the trailing newline
  • error: Error if the operation fails (may be io.EOF)

VT100 Terminal Creation

Create a VT100 terminal for interactive line-based input.

func NewTerminal(c io.ReadWriter, prompt string) *Terminal

Runs a VT100 terminal on the given ReadWriter. If the ReadWriter is a local terminal, that terminal must first have been put into raw mode. The prompt is a string that is written at the start of each input line (e.g., "> ").

Parameters:

  • c io.ReadWriter: ReadWriter for terminal I/O
  • prompt string: Prompt string to display at the start of each input line

Returns:

  • *Terminal: New Terminal instance configured with the given ReadWriter and prompt

Terminal Line Reading

Read lines of input from a VT100 terminal.

func (t *Terminal) ReadLine() (line string, err error)

Returns a line of input from the terminal. Supports history navigation with up/down arrows, cursor movement, and line editing.

Returns:

  • line string: Input line read from the terminal
  • err error: Error if the operation fails (may be io.EOF or ErrPasteIndicator)
func (t *Terminal) ReadPassword(prompt string) (line string, err error)

Temporarily changes the prompt and reads a password, without echo, from the terminal. The AutoCompleteCallback is disabled during this call.

Parameters:

  • prompt string: Prompt to display for password input

Returns:

  • line string: Password entered (without trailing newline)
  • err error: Error if the operation fails

Terminal Prompt Management

Manage the prompt displayed by the terminal.

func (t *Terminal) SetPrompt(prompt string)

Sets the prompt to be used when reading subsequent lines.

Parameters:

  • prompt string: New prompt string to display

Terminal Size Management

Manage terminal dimensions for proper display.

func (t *Terminal) SetSize(width, height int) error

Sets the terminal size. This updates the internal state to match the new dimensions.

Parameters:

  • width int: Terminal width in columns (minimum 1)
  • height int: Terminal height in rows

Returns:

  • error: Error if the operation fails

Terminal Writing

Write data to the terminal.

func (t *Terminal) Write(buf []byte) (n int, err error)

Implements the io.Writer interface for the terminal. Handles proper display of output while preserving the current input line and cursor position.

Parameters:

  • buf []byte: Data to write to the terminal

Returns:

  • n int: Number of bytes written
  • err error: Error if the operation fails

Bracketed Paste Mode

Control bracketed paste mode for terminals that support it.

func (t *Terminal) SetBracketedPasteMode(on bool)

Requests that the terminal bracket paste operations with markers. Not all terminals support this but, if it is supported, then enabling this mode will stop any autocomplete callback from running due to pastes. Additionally, any lines that are completely pasted will be returned from ReadLine with the error set to ErrPasteIndicator.

Parameters:

  • on bool: true to enable bracketed paste mode, false to disable

Types

State

type State struct {
	// Contains unexported platform-specific fields
}

Contains the state of a terminal. Used to save and restore terminal settings. The internal structure varies by platform (Unix, Windows, Plan 9) but the type provides a consistent interface across all platforms.

Usage:

  • Returned by MakeRaw() and GetState()
  • Passed to Restore() to restore previous terminal state
  • Opaque type - should not be inspected or modified directly

Terminal

type Terminal struct {
	// AutoCompleteCallback, if non-null, is called for each keypress with
	// the full input line and the current position of the cursor (in
	// bytes, as an index into |line|). If it returns ok=false, the key
	// press is processed normally. Otherwise it returns a replacement line
	// and the new cursor position.
	//
	// This will be disabled during ReadPassword.
	AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool)

	// Escape contains a pointer to the escape codes for this terminal.
	// It's always a valid pointer, although the escape codes themselves
	// may be empty if the terminal doesn't support them.
	Escape *EscapeCodes

	// History records and retrieves lines of input read by ReadLine which
	// a user can retrieve and navigate using the up and down arrow keys.
	//
	// It is not safe to call ReadLine concurrently with any methods on History.
	//
	// NewTerminal sets this to a default implementation that records the
	// last 100 lines of input.
	History History

	// Contains unexported fields for internal terminal state
}

Contains the state for running a VT100 terminal that is capable of reading lines of input. Provides readline-like functionality with history, cursor movement, line editing, and autocomplete support.

Exported Fields:

  • AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool): Optional callback function invoked for each keypress to provide autocomplete functionality. If it returns ok=true, the returned newLine and newPos replace the current line and cursor position. Disabled during ReadPassword() calls.

  • Escape *EscapeCodes: Pointer to escape codes for terminal styling. Always a valid pointer, though escape codes may be empty if the terminal doesn't support them.

  • History History: Interface for managing command history. Allows users to navigate previous input using up/down arrow keys. NewTerminal sets this to a default implementation storing the last 100 lines.

Concurrency: The Terminal type is not safe for concurrent use. It uses internal locking to protect against concurrent Write() and key press handling, but external synchronization is required for other concurrent access patterns.

EscapeCodes

type EscapeCodes struct {
	// Foreground colors
	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte

	// Reset all attributes
	Reset []byte
}

Contains escape sequences that can be written to the terminal in order to achieve different styles of text. Each field contains the ANSI escape sequence as a byte slice.

Fields:

  • Black []byte: Escape sequence for black foreground color
  • Red []byte: Escape sequence for red foreground color
  • Green []byte: Escape sequence for green foreground color
  • Yellow []byte: Escape sequence for yellow foreground color
  • Blue []byte: Escape sequence for blue foreground color
  • Magenta []byte: Escape sequence for magenta foreground color
  • Cyan []byte: Escape sequence for cyan foreground color
  • White []byte: Escape sequence for white foreground color
  • Reset []byte: Escape sequence to reset all text attributes to default

Usage: Access via Terminal.Escape field. Write the byte slices directly to the terminal to apply colors.

History

type History interface {
	// Add will be called by Terminal.ReadLine to add
	// a new, most recent entry to the history.
	// It is allowed to drop any entry, including
	// the entry being added (e.g., if it's deemed an invalid entry),
	// the least-recent entry (e.g., to keep the history bounded),
	// or any other entry.
	Add(entry string)

	// Len returns the number of entries in the history.
	Len() int

	// At returns an entry from the history.
	// Index 0 is the most-recently added entry and
	// index Len()-1 is the least-recently added entry.
	// If index is < 0 or >= Len(), it panics.
	At(idx int) string
}

A History provides a (possibly bounded) queue of input lines read by Terminal.ReadLine. Users can navigate through history entries using up/down arrow keys.

Methods:

  • Add(entry string): Called by Terminal.ReadLine to add a new entry to the history. Implementations may drop entries (including the new entry, the oldest entry, or any other entry) to maintain size bounds or filter invalid entries.

  • Len() int: Returns the number of entries currently in the history.

  • At(idx int) string: Returns an entry from the history. Index 0 is the most recent entry, and index Len()-1 is the oldest entry. Panics if idx < 0 or idx >= Len().

Default Implementation: NewTerminal sets Terminal.History to a default ring buffer implementation that stores the last 100 lines of input.

Concurrency: It is not safe to call ReadLine concurrently with any methods on History. The History interface methods may be called by ReadLine, so external synchronization is required if accessing History while ReadLine may be running.

Variables

ErrPasteIndicator

var ErrPasteIndicator = pasteIndicatorError{}

May be returned from ReadLine as the error, in addition to valid line data. It indicates that bracketed paste mode is enabled and that the returned line consists only of pasted data. Programs may wish to interpret pasted data more literally than typed data.

Type: error

Usage:

line, err := terminal.ReadLine()
if err == term.ErrPasteIndicator {
	// Line was pasted, not typed
	// Handle pasted data (e.g., disable auto-formatting)
} else if err != nil {
	// Other error
}

Platform Support

The package provides platform-specific implementations for:

  • Unix/Linux: Full support for all features
  • Windows: Full support with Windows console API
  • Plan 9: Full support with Plan 9 terminal semantics
  • BSD variants: Specialized support for BSD systems
  • Other platforms: Limited support via fallback implementations

The API remains consistent across all platforms, with platform-specific behavior handled internally.

Common Patterns

Safe Terminal Mode Handling

Always use defer to ensure terminal state is restored:

oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
	return err
}
defer term.Restore(int(os.Stdin.Fd()), oldState)

// Use raw mode terminal...

Terminal Size Detection

Get terminal dimensions for proper display:

width, height, err := term.GetSize(int(os.Stdout.Fd()))
if err != nil {
	// Handle error or use default dimensions
	width, height = 80, 24
}

Interactive Shell with History

// Put terminal in raw mode
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
	panic(err)
}
defer term.Restore(int(os.Stdin.Fd()), oldState)

// Create terminal
terminal := term.NewTerminal(os.Stdin, "$ ")

// Read commands in a loop
for {
	line, err := terminal.ReadLine()
	if err == io.EOF {
		break
	}
	if err != nil {
		panic(err)
	}

	// Process command
	fmt.Printf("Executing: %s\n", line)
}

Custom Autocomplete

terminal := term.NewTerminal(os.Stdin, "> ")

// Set up autocomplete callback
terminal.AutoCompleteCallback = func(line string, pos int, key rune) (string, int, bool) {
	if key == '\t' {
		// Implement tab completion
		completed := autoComplete(line[:pos])
		newLine := completed + line[pos:]
		return newLine, len(completed), true
	}
	return "", 0, false
}

line, err := terminal.ReadLine()

Notes

  • On non-Unix systems, os.Stdin.Fd() may not be 0
  • The Terminal type is not safe for concurrent access (except for concurrent Write and ReadLine)
  • History methods should not be called concurrently with ReadLine
  • AutoCompleteCallback is disabled during ReadPassword operations
  • The default history implementation stores the last 100 lines
  • Bracketed paste mode is not supported by all terminals
  • Raw mode must be enabled before creating a Terminal for local terminal I/O