Skip to content

Contributing

Gaurav Gosain edited this page Oct 15, 2026 · 4 revisions

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 pure Go emulator by default; ./scripts/install.sh ghostty builds the libghostty-vt backend. 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 and every push to main. Run the first set 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.

Two more workflows run on every pull request:

  • Lint (.github/workflows/lint.yml): golangci-lint v2 with the repository's .golangci.yml (the standard linters plus gosec), govulncheck ./..., and go vet ./... with GOOS set to darwin, windows, freebsd and openbsd. Run golangci-lint run ./... locally. A finding that is wrong for one line gets a //nolint comment with its reason on that line.
  • Binary size (.github/workflows/binary-size.yml): scripts/binary-size.sh builds tuios the way the release does (CGO_ENABLED=0, -trimpath, -ldflags "-s -w") for linux/amd64 and darwin/arm64 and fails when a binary is over its budget. Run the script locally to see the size and the room left. To raise a budget, measure the new size on the Go version go.mod names and say in the commit what grew and why.

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:

Suite Command Covers
End-to-end TUI cd e2e/tui && TUIOS_E2E=1 go test -count=1 -timeout 40m . A real tuios in a real PTY, checked on screen. A separate Go module. Set TUIOS_E2E_BIN to a built binary, or the suite builds one
Control plane go test -tags e2e ./e2e/... Real daemons driven through the CLI
Go libraries (Added in v0.10.0) go test ./vt/... ./swatch/... ./progstatus/... tuios.dev/vt, tuios.dev/swatch and tuios.dev/progstatus. Each is a Go module of its own, so ./... from the root stops at it
ghostty backend PKG_CONFIG_PATH="$PWD/.ghostty-vt/native/pkgconfig" go test -tags ghostty -count=1 -short ./vt/ ./internal/session/ ./internal/terminal/ ./internal/app/ ./internal/input/ ./cmd/tuios/ The libghostty-vt emulator and the packages whose tests link it. go build -tags ghostty ./... alone runs none of these tests
Differential go test -tags differential ./vt/ -run TestDifferential The emulator against tmux. Needs tmux
Browser cd clienttests && npm install && npm test tuios-web in the system Chromium, with Playwright

Warning

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

The repository prefers end-to-end tests: a real tuios binary against real daemons, in e2e/tui. The rules, from its AGENTS.md:

  • Write the test first, not after the code. If you must test a part in isolation, first write down the ways it can fail.
  • A test that claims to cover a bug must fail on a build with the fix removed. e2e/tui/NEGATIVE_CONTROLS.md records those runs.
  • An end-to-end test should leave an artifact you can check again, such as a screenshot or a capture.
  • A unit test stays only when it catches a real bug the end-to-end suite misses: emulator conformance, fuzz targets, wire compatibility, security boundaries, deterministic race regressions and performance budgets.

For emulator changes, add a case to the conformance corpus in vt/, the tuios.dev/vt module. Unit tests that stay live in *_test.go next to the code, use t.Run subtests, and name benchmarks Benchmark*.

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:

    Prefix Use 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.

Note

Security issues

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

Related

Clone this wiki locally