This project uses Nix Flakes for development environment. We strongly recommend using Nix to ensure consistent tooling across all contributors.
# Enter the development environment
nix develop
# Build the project
cargo build
# Run tests
cargo nextest rundirenv automatically loads the Nix environment when you enter the project directory.
- Install direnv:
nix profile install nixpkgs#direnv - Add to your shell (bash/zsh/fish)
- Allow direnv in the project directory:
direnv allow
Then the development environment will load automatically every time you enter the project.
If you don't use Nix, you need to install the following tools manually:
Required:
- Rust (see
rust-toolchain.tomlfor version) - Cargo
- cargo-nextest
- protobuf (protoc)
- pkg-config
- libgit2
Optional (for formatting/linting):
- rustfmt
- treefmt
- nixfmt
- shfmt
- taplo
- hclfmt
Optional (for testing on Linux):
- xvfb-run
# Clone the project
git clone https://github.com/xrelkd/clipcat.git
cd clipcat
# Build
cargo build
cargo build --release
# Run
cargo run --package clipcatd# Debug build
cargo build
# Release build
cargo build --release
# Run a specific package
cargo run --package clipcatd# Run tests
cargo test
# Or use cargo-nextest (faster, used in CI)
cargo nextest run
cargo nextest run --releaseAlways run these before creating a commit:
# Format code
cargo fmt
# Or use treefmt
treefmt
# Or nix fmt (if using Nix)
nix fmt
# Run lints (fix all warnings/errors)
cargo clippy
cargo clippy-all --fixKeep commits clean:
- Fix all lints and compilation errors in the same commit as your feature/fix
- Do NOT create separate commits for lint fixes
- Keep commit messages concise and meaningful
Create feature/fix branches from develop:
# Feature branch
git checkout -b feat/my-new-feature develop
# Fix branch
git checkout -f fix/bug-description developSupported prefixes: feat/*, feature/*, fix/*, hotfix/*, release/*, ci/*
- Run formatters (
cargo fmt,treefmt, ornix fmt) - Run lints and fix all warnings/errors (
cargo clippy-all --fix) - Ensure tests pass (
cargo nextest run) - Push your branch to your fork
- Create a PR targeting the
developbranch - Ensure all CI checks pass
- Keep commits clean, concise, and follow the commit message convention
This project follows Conventional Commits specification.
<type>(<scope>): <description> (#PR)
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
refactor |
Code refactoring |
docs |
Documentation updates |
style |
Code formatting (no logic changes) |
ci |
CI/CD modifications |
chore |
Maintenance tasks |
build |
Dependency updates |
The scope is optional but recommended when the change affects a specific component.
Each commit should only affect one scope. If your PR modifies multiple components, create separate commits for each one.
Good:
# Commit 1
fix(crates/base): fix lints and errors
# Commit 2
fix(clipcatctl): fix lints and errorsBad:
# Don't do this
fix: fix lints and errors in crates/base and clipcatctlLint fixes should be part of the feature commit. Do not create separate commits for fixing lints or compilation errors.
| Scope | Description |
|---|---|
clipcatd |
Daemon component |
clipcatctl |
CLI control tool |
clipcat-menu |
Menu component |
clipcat-notify |
Notification component |
crates/base |
Base/common crate |
crates/cli |
CLI utilities crate |
crates/client |
gRPC client crate |
crates/clipboard |
Clipboard crate |
crates/proto |
Protocol definitions crate |
crates/server |
gRPC server crate |
actions |
GitHub Actions workflows |
nix |
Nix NixOS modules |
Some commits don't require a scope:
style: apply formatterchore: update Rust formatterbuild(deps): update Cargo.lock
# Feature in multiple scopes - create separate commits
feat(crates/clipboard): add new clipboard listener for Wayland
feat(clipcatd): integrate new clipboard listener
# Feature
feat(clipcatd): add history clearing on startup
# Bug Fix
fix(clipcat-menu): pass SkimOptions by value to Skim::run_with
# Refactor
refactor(crates/clipboard): remove clippy suppression and `FIXME`
# Documentation
docs(readme): document rofi delete keybinding
# CI/CD
ci(actions): add `--fix-missing` to `apt install` in release workflow
# Chore
chore(gitignore): add `aider` ignore pattern
chore(nix): extract `name` from the `Cargo.toml` file
# Style (no scope needed)
style: apply formatter
# Dependency Update (usually automated)
build(deps): bump tokio from 1.49.0 to 1.50.0 (#969)When submitting a PR that touches multiple scopes, use multiple commits:
# If your PR modifies both crates/base and clipcatctl
fix(crates/base): fix lints and errors
fix(clipcatctl): fix lints and errors
# Then merge with "Merge pull request #123"Always reference the PR number when applicable:
feat(clipcatd): add new feature (#123)