Contributing to Trek¶
Trek welcomes contributions. The development workflow is strict but straightforward — it exists to keep the codebase clean and releases reliable.
Before You Start¶
Read the open issue you intend to work on carefully. Extract two things before writing any code:
- The desired behavior — what should Trek do that it doesn't do today, or what should it stop doing?
- The acceptance criteria — how will you and reviewers know the work is complete?
If either of these is unclear, ask in the issue before opening a branch.
Development Workflow¶
Every change follows this sequence, without exception:
- Read the issue. Extract desired behavior and acceptance criteria.
- Write a failing test first. Tests are written in BDD style: Given a starting state, When an action occurs, Then the outcome is X.
- Implement the minimum change needed to satisfy the test.
- Make all tests pass.
- Run the quality gates (see below). All four must pass.
- Bump the version in
Cargo.tomland add a CHANGELOG entry under[Unreleased]. - Open a PR with a conventional commit message.
Do not skip steps. In particular, do not write the implementation before the test — the test defines the contract that the implementation must satisfy.
Quality Gates¶
Run these four commands before every commit. All four must pass with zero warnings and zero errors:
Warnings may not be suppressed with #[allow(...)] without a justification
comment explaining why the suppression is appropriate. Reviewers will ask about
any suppression that lacks an explanation.
Commit Messages¶
Trek uses Conventional Commits. Every commit message must follow this format:
<type>(<scope>): <description>
<body — explain WHY, not what>
Closes #<issue-number>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Types:
| Type | When to use |
|---|---|
feat |
New feature or new keybinding |
fix |
Bug fix |
docs |
Documentation changes only |
style |
Code formatting, no logic change |
refactor |
Internal restructuring, no behavior change |
test |
Adding or updating tests |
chore |
Maintenance, tooling, CI/CD |
Scopes:
| Scope | Area of the codebase |
|---|---|
nav |
Navigation and directory traversal |
preview |
Preview pane and preview modes |
search |
Fuzzy search and ripgrep content search |
icons |
File type icons |
mouse |
Mouse input handling |
shell |
Shell integration (trek --install-shell) |
ci |
CI/CD workflows |
release |
Version bumps, CHANGELOG, Homebrew formula |
The body should explain why the change is being made, not describe what the diff contains. Reviewers can read the diff; they benefit from understanding your reasoning.
Branch Naming¶
Branches follow this pattern:
Examples:
feat/issue-34-marks-bookmarks
fix/issue-12-preview-crash
refactor/issue-67-datetime-module
docs/issue-88-keybinding-reference
Use the issue number. If there is no issue for the work you want to do, open one first.
Version Bumping¶
Trek follows Semantic Versioning. Choose the version component to bump based on the nature of the change:
| Change type | Version component |
|---|---|
| Bug fix, refactor, documentation | PATCH (0.x.y) |
| New feature, new keybinding | MINOR (0.x.0) |
| Breaking change — different keybindings, removed flag, changed behavior | MAJOR (x.0.0) |
Update Cargo.toml and add an entry to CHANGELOG.md under the [Unreleased]
heading. Do not create a new heading — the release process handles that.
Release Process¶
Do not push a release tag until CI is green for the commit you intend to tag. Verify CI status first:
Once CI is green, tag and push:
The release workflow handles the rest:
- Builds macOS binaries for
aarch64andx86_64 - Uploads the binaries as GitHub release assets
- Updates the Homebrew formula in
bradleyfay/homebrew-trekautomatically
Do not manually edit the Homebrew formula or create the GitHub release yourself. The workflow does both.
Architecture Principles¶
Trek's codebase is organized around SOLID principles. Keep these in mind when deciding where new code belongs and how to structure new types.
Single Responsibility — each module does one thing. A module that handles directory listing does not also handle preview rendering.
Open/Closed — extend Trek's behavior by adding new types that implement existing traits. Avoid patching existing types to handle new cases.
Liskov Substitution — if a type implements a Trek trait, it must be fully substitutable for any other implementation of that trait. Partial implementations that panic or no-op on certain inputs are not acceptable.
Interface Segregation — traits should be narrow and focused. A type that only needs to read files should not be required to implement a trait that also writes files.
Dependency Inversion — depend on abstractions, not concrete I/O. Code that
operates on files should accept a trait object or generic parameter, not a
direct reference to std::fs. This is what makes the codebase testable without
a real filesystem.
Cohesion — modules that change together stay together. If two pieces of code are always modified in the same PR, they probably belong in the same module.
Getting Help¶
If you are unsure whether a contribution fits Trek's scope, open a discussion
on the issue before starting work. The vision document at
CLAUDE.md defines what Trek is and is not — checking a
proposed feature against that document before implementing it will save
everyone time.