Contributing

Build TUIOS from source, run the tests, and send a pull request.

Contributions are welcome: bug reports, fixes, tests and documentation. This page covers building from source, the checks CI runs, and how to send a change.

The tuios repository has an AGENTS.md with a package map and the test commands. Read it before a larger change.

Build

You need Go 1.26.6 or later (the version in go.mod), Git, and a Nerd Font to see the icons. --ascii-only works without one.

git clone https://github.com/Gaurav-Gosain/tuios
cd tuios

go build -o tuios ./cmd/tuios
go build -o tuios-web ./cmd/tuios-web

./tuios --standalone --debug

--standalone runs TUIOS without the daemon, which is simpler while you work on the UI. Without it, TUIOS starts or reuses a daemon from the same binary.

The default build uses the pure Go terminal emulator and needs no C toolchain. The libghostty-vt backend uses cgo and needs Zig 0.16 or later:

./scripts/ghostty-lib.sh
PKG_CONFIG_PATH="$PWD/.ghostty-vt/native/pkgconfig" go build -tags ghostty ./cmd/tuios

./scripts/install.sh builds and installs the ghostty backend by default. See docs/ghostty-vt.md in the repository for details.

With Nix:

nix develop    # development shell
nix build      # build the package
nix run        # build and run

Checks

CI runs these on every pull request. Run them before you push:

gofmt -l .          # must print nothing
go vet ./...
go build ./...
go test ./... -count=1 -timeout 20m

CI also checks that go.mod is tidy in both the root module and e2e/tui, and runs go test -race ./... every night. There is no golangci-lint config. If you run a linter locally, keep unrelated lint fixes out of your pull request.

The full suite is slow and uses every core. To leave the machine usable while it runs:

nice -n 10 go test ./... -timeout 20m

Other test suites

go test ./... from the root does not run these:

SuiteCommandCovers
End-to-end TUIcd e2e/tui && TUIOS_E2E=1 go test -count=1 ./...A real tuios in a real PTY, checked on screen. A separate Go module
Control planego test -tags e2e ./e2e/...Real daemons driven through the CLI
ghostty backendPKG_CONFIG_PATH="$PWD/.ghostty-vt/native/pkgconfig" go test -tags ghostty -count=1 -short ./internal/vt/ ./internal/session/ ./internal/terminal/The libghostty-vt emulator
Differentialgo test -tags differential ./internal/vt/ -run TestDifferentialThe emulator against tmux. Needs tmux
Browsercd clienttests && npm install && npm testtuios-web in the system Chromium, with Playwright

Without TUIOS_E2E=1 the end-to-end suite skips every test and reports success. Always pass -count=1 too: a cached result can survive a change of binary. Run this suite if you change rendering, input handling or the daemon protocol.

Writing tests

  • Put tests in *_test.go next to the code.
  • Prefer table-driven tests with t.Run subtests.
  • Name benchmarks Benchmark*.
  • For emulator changes, add a case to the conformance corpus in internal/vt/. The repository's AGENTS.md explains how it works.
func TestFeature(t *testing.T) {
	tests := []struct {
		name string
		in   string
		want string
	}{
		{"empty", "", ""},
		{"word", "abc", "ABC"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := Feature(tt.in); got != tt.want {
				t.Errorf("Feature(%q) = %q, want %q", tt.in, got, tt.want)
			}
		})
	}
}

Code style

  • Follow Effective Go and run gofmt.
  • Every package has a package comment, and exported names have doc comments.
  • Wrap errors with context: fmt.Errorf("failed to load config: %w", err).
  • Keep functions small and testable.

Pull requests

  1. Fork the repository and create a branch:

    git checkout -b fix/close-last-window
  2. Make the change, with tests. Update the docs if behavior changes.

  3. Commit with a conventional commit prefix:

    PrefixUse for
    feat:A new feature
    fix:A bug fix
    docs:Documentation
    refactor:A change that does not alter behavior
    test:Tests
    chore:Maintenance
    git commit -m "fix: panic when closing the last window"
  4. Push and open a pull request. The template asks what changed, why, and how you tested it. Include a screenshot or recording for UI changes, and link the related issue.

  5. Address review comments. Keep commits focused, and rebase on main if asked.

Reporting issues

Open an issue on GitHub. The bug template asks for:

  • the TUIOS version (tuios --version),
  • your platform and how you installed TUIOS,
  • steps to reproduce, and what you expected,
  • logs, if you have them (tuios logs for the daemon, tuios --debug for the client).

Use Discussions for questions and ideas. Issues labeled good first issue are a good place to start.

Security issues

Do not open a public issue for a vulnerability. Email the maintainer as described in SECURITY.md.

On this page