This unpublished Elixir package is under implementation. Pure foundation tests, packed-core import checks and owned real-tmux checks are available. WRITING.md governs prose, comments, and commits.
Setup
Use mise with the ranges in .tool-versions: Erlang/OTP
29.x and Elixir 1.20.x. The Mix project requires at least Elixir 1.20.4.
Linux builds also require a C11 compiler and Linux headers for the owned
I/O helper. No NIF or third-party runtime package is required. CC may name
one compiler executable. Install prerequisites before timing checks:
$ mise install
To install newer releases within those ranges without editing the file:
$ mise upgrade erlang elixir
With mise active in your shell, verify that Elixir runs on OTP 29 and was
compiled for OTP 29:
$ elixir --version
Mise selects the newest OTP build for an Elixir prefix; the prefix does not
lock the OTP suffix. If a future 1.20 patch adds a newer OTP build, select
its exact 1.20.x-otp-29 version. asdf requires exact versions and cannot
consume these floating ranges directly.
CI reads both ranges from .tool-versions and passes them to setup-beam
in loose mode, which selects the Elixir build for the installed OTP major.
The action's direct version-file mode requires exact versions.
The native Linux matrix reads exact tmux source revisions and the reference
Elixir/OTP pair from priv/tmux/support.json. It also tests the resolved
.tool-versions pair with the newest listed tmux release. Every cell checks
the actual OTP patch, Elixir version and compiled OTP major before testing.
Missing prerequisites fail the cell. Required Linux checks succeeds only
when the core checks and every native cell succeed; no macOS job is required.
Hex is required only for package archive checks. Install it separately from the check loops if it is missing:
$ mix local.hex --force
The core has no third-party runtime dependencies. ExDoc is a development-only dependency; install it before timing documentation checks:
$ mix deps.get
tmux is not needed for pure unit or packed-core checks. The
implementation floor is tmux 3.3, and support must be proved against that
version rather than inferred from a newer local binary.
Current checks
Check that the active runtime matches the development selectors, minimum versions and compiled OTP major:
$ time elixir scripts/check_runtime.exs tracking
Use reference instead of tracking to require the exact reference pair.
Check formatting after an edit:
$ time mix format --check-formatted
Before handing off a change, validate the Mix project with warnings treated as errors:
$ time mix compile --warnings-as-errors
Check public function specs and type documentation against the compiled API:
$ time mix run scripts/check_public_contracts.exs
Compile the consumer fixtures and check the expected Elixir 1.20 diagnostics:
$ time mix run scripts/check_consumer_types.exs
Typespecs document contracts; the compiler infers types from implementation patterns and guards. These fixtures verify selected valid and invalid uses, not arbitrary criteria or every value-dependent return type. The codec fixture records a case inference does not currently reject; runtime validation remains required. Neither a declaration count nor a silent compiler proves every contract.
With dependencies already installed, render the public reference and guides:
$ time mix docs --warnings-as-errors
Check rendered local files and HTML fragments without network requests:
$ time python3 scripts/check_docs_links.py
The link check reports ExDoc's optional host-provided version catalogue separately. It does not verify external websites or publication.
Set DOCS_SOURCE_REF to the reviewed commit, branch or release tag when building
documentation for that revision. ExDoc uses main by default. Rendered copies
resolve source-file and artwork-directory links without changing the originals.
With Hex already installed, build the local archive:
$ time mix hex.build
Run critical pure tests in the inner loop, or all unit tests in the mid loop:
$ time mix test
Check generated field, operator and relation documentation after schema changes:
$ time mix run scripts/generate_schema.exs --check
Regenerate it with mix run scripts/generate_schema.exs before the check.
The default suite excludes the integration tag. Linux integration fixtures
require Python 3.9+ with pidfd support and an explicit tmux executable or tmux
on PATH. Python is a development fixture tool, not a core runtime dependency.
The helper owns a foreground tmux server, observes socket readiness through
inotify and verifies server/pane exit through process handles. It uses no
fixed readiness sleeps and never starts the default server.
Run the real fixture checks in the outer loop with the exact tmux binary being qualified:
$ LIBTMUX_TMUX=/path/to/tmux mix test --include integration
CI runs the complete existing suite with two ExUnit cases at once and two BEAM schedulers to fit the Linux runner. The native tests still exercise their explicit concurrent fault schedules. Source download, prerequisites and tmux compilation run before the timed test step. These cells qualify implemented cases; they do not establish unimplemented API support.
Check packed-core consumption and metadata outside the checkout:
$ time mix run scripts/check_package.exs
Real checks round-trip command and format syntax with hostile bytes. The field encoder protects backslashes and control bytes before tmux prints them; the decoder handles one free-form field per response. It does not assume separator bytes cannot occur in values. The pure control parser enforces byte/event limits, but transport receive bounds and shared lane safety need separate qualification.
The ownership guide describes the one-shot helper, resource ceilings and remaining distribution gates.
These gates prove current foundations and fixture ownership. They do not establish a complete client API, installed adapter graphs or compatibility for unexercised operations. Do not add empty source or tests to make a command appear useful. Complete runnable examples and adapter consumer checks arrive with those components.
Check budgets
Time the entire command, including startup and setup. Record duration and scope in the pull request. Tool installation happens before a timed loop.
| Loop | Budget | Stretch | Scope |
|---|---|---|---|
| Inner | Under 5 seconds | Under 2 seconds | Formatting or critical tests for the edited code |
| Mid | Under 30 seconds | Under 10 seconds | Unit suites, lint, and generated-file checks |
| Outer | Under 5 minutes | Under 60 seconds | Compilation, packaging, docs, and integration matrices |
Formatting and changed pure tests belong in the inner loop; the complete unit suite belongs in the mid loop. Compilation, packaging and real tmux fixtures and documentation rendering belong in the outer loop. Dependency installation stays outside all check loops. Do not run network operations, installs, builds, browsers, sleeps, or broad corpus scans in the inner or mid loop.
Investigate waits longer than one second; use events and subscriptions for readiness instead of fixed sleeps. Slow tests need an outer-loop tag and a one-line reason. Fix redundant setup, polling, and slow paths before adding tests to an over-budget loop. Benchmarks are separate: each run stays under 10 minutes, and a full sweep stays under one hour.
Package boundaries
mix.exs owns the core package. The workspace loader and MCP server have separate Mix projects that consume the core. Do not add adapter dependencies or adapter configuration to the core. The design note records the planned behavioral boundaries.
Adding implementation
Add tests for critical behavior and regressions, not copies of the implementation. A regression test must fail for the intended reason before its passing result becomes evidence. Prefer pure ExUnit tests for parsing, encoding, and selection; exercise protocol and resource ownership against real tmux as well.
Every tmux fixture uses a unique, owned socket and temporary directory.
Clear inherited TMUX and TMUX_PANE. Never connect tests to the default
server, and only stop servers or remove files owned by that run. Use
bounded, event-based readiness and verify cleanup on success and failure.
Use ExUnit supervision for BEAM children and explicit teardown for owned OS processes. A successful teardown call is not proof that a child exited. Enable asynchronous tests only when sockets, state, and cleanup are isolated. Distinguish protocol acknowledgement from operation completion in assertions.
Each support claim needs its own required CI cell. The tmux floor must run
against tmux 3.3 itself; 3.3a is a separate compatibility case. Platform
and transport coverage remain unverified until implementation exercises
them. Missing prerequisites in a required cell fail that cell; report
optional skips explicitly.
Pull requests
Keep changes on a topic branch in a separate worktree. Preserve unrelated edits and keep each PR focused on one reviewable change. Follow the commit format in WRITING.md.
Describe the problem, resulting behavior, and relevant validation. Report passing, failing, skipped, and unverified checks separately. Scope claims to what the checks actually exercise; scaffold validation cannot establish runtime compatibility, performance, or release readiness.
Publication
Pushing a v<version> tag runs the required Linux checks at that revision,
then publishes the core package and its documentation to public Hex. The
tag must match the root Mix version. The publishing job uses HEX_API_KEY
from the GitHub environment named hex, then verifies the public release
and an installation outside the checkout. Merges and local archive builds
do not publish. Creating a release tag requires separate authorization.
Workspace and MCP have no publication jobs. Their eventual releases must use real dependency versions and pass their own installed-consumer checks.