Documentation

Glazier is a one-person project that grew a test matrix larger than itself. If you want to add to it, this page is the short version of what the repository expects from a change. The long version is CONTRIBUTING.md, and the very long version, the one with the reasoning behind every odd decision, is AGENTS.md. Read that one before you “simplify” anything in the command runner. Each piece is there because a shell bit me.

Scope

In scope:

  • The profile syntax.
  • The tmux client library.
  • The CLI commands.
  • The quality of the diagnostics.
  • The documentation.

Out of scope:

  • Anything that belongs in your tmux.conf, for example key bindings or the status line.
  • Support for a multiplexer other than tmux.

Getting started

You need Go 1.26 or later and tmux on your PATH. The end-to-end test skips itself without tmux, but you want it to run.

Console
$ git clone https://github.com/wilhelm-murdoch/glazier.git
$ cd glazier
$ make test

The Makefile pins each tool and runs it with go run <tool>@<version>. No global install and no bootstrap script is necessary. The pinned tools download on first use.

Makefile targets

TargetWhat it does
make testRuns the unit tests with gotestsum.
make raceRuns the unit tests under the race detector. CGO is required.
make lintRuns golangci-lint with gosec. The configuration is in .golangci.yml.
make coverRuns the unit tests with coverage. It fails under the 80% floor.
make vulnRuns the govulncheck vulnerability scan.
make fuzzFinds and runs each native Go Fuzz* target. FUZZTIME is 10 s for each target.
make vetRuns go vet.
make fmtRuns gofmt on the tree.
make buildBuilds a version-stamped binary at bin/<os>-<arch>/glaze.
make e2eRuns every end-to-end case on the tmux in your PATH. Set RUN='TestX/case' to filter.
make e2e-matrixRuns every end-to-end case on six tmux targets in Docker. Set BASE=github/main to compare with a base revision.
make allRuns deps, build, test, race, lint, cover, vuln and the checks of the e2e module.

CI calls these same targets. A green local make all is a green build. CI also runs the tests on macOS, on the minimum supported Go version and on the latest stable release, and runs the end-to-end matrix. See Compatibility for the targets.

How the code is organised

  • cmd/glaze/main.go wires the CLI with urfave/cli/v3. There is one entry for each subcommand.
  • cmd/glaze/actions/ holds one file for each subcommand. base.go holds the shared profile resolution and the diagnostics scaffolding.
  • internal/spec/ holds the hcldec specification tree for the profile schema.
  • internal/decoders/ decodes the raw cty.Value into the typed Session, Window and Pane structs.
  • internal/parser/ wraps hclparse, collects the variables from --var and GLAZE_ENV_* and holds the template function table.
  • internal/diagnostics/ renders the Terraform-style diagnostics and holds the custom validators for layout strings, directories and sizes.
  • pkg/tmux/ is the tmux client library. Every tmux call goes through the Commander interface, which is the seam that the tests use. e2e_test.go drives a real tmux server on a throwaway socket.
  • pkg/files/ resolves the profile path and expands ~.
  • e2e/ is a separate module. It runs the compiled binary against real tmux servers and never imports Glazier.

Adding or changing behaviour

  1. New behaviour needs a test. Fakes go through tmuxtest.Recorder or OverrideCommandFactory. Never start tmux in a unit test.
  2. A change that touches shared mutable state must stay safe under -race. Run make race.
  3. A user-facing error is an HCL diagnostic where a profile is involved. Extend the validators in internal/diagnostics. Do not return a bare error.
  4. A new profile attribute needs a spec entry, a decoder field, a validator if the value is constrained, documentation in the README and a test at each layer.

Pull requests

  • Keep a change focused. Put unrelated work in a separate pull request.
  • Write a clear, imperative commit message that explains the why.
  • Make sure that make test, make race, make lint and make vet pass.
  • Add a test for each new behaviour.

For a security problem, do not open a pull request or a public issue. See Security and SECURITY.md.

Licence

Glazier is released under the MIT Licence. When you contribute, you agree that your work is licensed under the same licence.

AI disclosure

The architecture, the functionality and the base structure of this project are my own. I use AI as a tool for time-consuming work: documentation, tests and bug hunting. I also use it as a sounding board for structural decisions that keep the project easy to adopt and maintain. For a solo developer it is a force multiplier for high-quality code. There is always a human as a final verification step. It is a tool for drudgery and toil, not a crutch.