# Contributing

URL: https://tuios.dev/docs/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`](https://github.com/Gaurav-Gosain/tuios/blob/main/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](https://www.nerdfonts.com/) to see the icons. `--ascii-only` works without one.

```bash
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](https://ziglang.org/) 0.16 or later:

```bash
./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:

```bash
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:

```bash
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:

```bash
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 ./...`                                                                                                  | A real `tuios` in a real PTY, checked on screen. A separate Go module |
| Control plane   | `go test -tags e2e ./e2e/...`                                                                                                                       | Real daemons driven through the CLI                                   |
| ghostty backend | `PKG_CONFIG_PATH="$PWD/.ghostty-vt/native/pkgconfig" go test -tags ghostty -count=1 -short ./internal/vt/ ./internal/session/ ./internal/terminal/` | The libghostty-vt emulator                                            |
| Differential    | `go test -tags differential ./internal/vt/ -run TestDifferential`                                                                                   | The emulator against tmux. Needs `tmux`                               |
| Browser         | `cd clienttests && npm install && npm test`                                                                                                         | `tuios-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.

```go
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](https://go.dev/doc/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:

   ```bash
   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](https://www.conventionalcommits.org/) 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                           |

   ```bash
   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](https://github.com/Gaurav-Gosain/tuios/issues). 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](https://github.com/Gaurav-Gosain/tuios/discussions) for questions and ideas. Issues labeled [`good first issue`](https://github.com/Gaurav-Gosain/tuios/labels/good%20first%20issue) 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](https://github.com/Gaurav-Gosain/tuios/blob/main/SECURITY.md).

## Related

*[An interactive figure goes here. Open the page to use it.](https://tuios.dev/docs/contributing)*
