Contributing to Clawker
August 16, 2026 · View on GitHub
Thanks for your interest in contributing to Clawker! This project is currently in alpha, maintained by a solo developer opening up for community contributions. All skill levels welcome.
Getting Started
Prerequisites
- Go 1.26+
- Docker running locally
- Git
Development Setup
git clone https://github.com/schmitthub/clawker.git
cd clawker
git submodule update --init
make clawker
export PATH="$PWD/bin:$PATH"
go install ./cmd/clawkerand barego build ./cmd/clawkerare unsupported — they fail at compile time because the four Linux assets (clawkerd,clawkercp,ebpf-manager,coredns-clawker) referenced by//go:embedare gitignored.make clawkerproduces them via the per-target chain (clawkerd-binary,cp-binary,ebpf-binary,coredns-binary) and then builds the host CLI. All four are plainCGO_ENABLED=0Go cross-compiles tolinux/$GOARCH; the only Docker hop is thebpf-bindingsextraction needed on macOS (where clang cannot emit BPF object files) — Linux contributors install the pinned BPF toolchain once withsudo make bpf-depsand everything builds natively. Themake release-embeds/make stage-embeds-{amd64,arm64}targets are for the goreleaser pipeline; contributors do not invoke them for local development.
Running Tests
Clawker has multiple test tiers. All relevant tests must pass before submitting a PR.
# Unit tests (no Docker required) — run these first
make test
# Integration tests (Docker required)
go test ./test/e2e/... -v -timeout 10m # E2E integration
go test ./test/whail/... -v -timeout 5m # Whail BuildKit integration
# All test suites
make test-all
Golden File Tests
Some tests use golden files for output comparison. To update golden files after intentional changes:
GOLDEN_UPDATE=1 go test ./path/to/package/... -run TestName -v
Code Style
Key Rules
- zerolog is for file logging only — user-visible output uses
fmt.Fprintfto IOStreams - Import boundaries are enforced:
- Only
internal/iostreamsimportslipgloss - Only
internal/tuiimportsbubbletea/bubbles - Only
internal/termimportsgolang.org/x/term - Only
pkg/whailwraps the Docker SDK; onlyinternal/dockerimportspkg/whail
- Only
- Cobra commands use
PersistentPreRunE(neverPersistentPreRun) - Output conventions: stdout for data, stderr for status/warnings/errors
- Error handling: Return typed errors to Main() — never print errors directly
Command Pattern
Every CLI command follows the Factory/Options/runF pattern:
NewCmd(f *cmdutil.Factory, runF func(*Options) error)constructor- Options struct declares only what the command needs
- Run function receives
*Options, never*Factory
See docs/architecture.mdx for the full pattern with examples.
Making Changes
Branch Naming
Use descriptive branch names:
feat/description— New featuresfix/description— Bug fixesrefactor/description— Code improvementsdocs/description— Documentation changes
What to Include in a PR
- Code changes with tests
- Updated documentation — if you change a package's public API, update its
CLAUDE.mdand relevant docs - Passing tests — run
make testat minimum before submitting - A changelog entry — if the PR changes the user surface or adds behavior (see below)
Changelog
The root CHANGELOG.md is the curated, human, user-facing changelog, in
Keep a Changelog format. It is not the
exhaustive commit log — that is generated per release into the GitHub release's
"Commits" section. CHANGELOG.md intentionally covers only the handful of
releases that change what a user sees or does.
- If your PR changes the user surface or adds behavior (a new command or
flag, a behavior change, a user-visible fix, a breaking change), add an entry
in the same PR, so it is committed before the release tag. Releases are
cut by tagging
main, and the release notes are rendered from the committed file — an entry added after the tag misses that release. - Tech-debt, refactor, chore, and dependency-bump PRs add nothing. They are not user-facing and do not belong in the curated changelog.
Entry format. Add a new ## [VERSION] - DATE section at the top, with the
Keep a Changelog ### Added / ### Changed / ### Fixed / ### Removed body.
Also add the matching reference-link line at the bottom of the file. The format
is plain Keep a Changelog — there is no per-entry metadata; the whole section
body is rendered verbatim as markdown.
## [0.13.0] - 2026-07-01
### Added
- **Headline of the change.** A sentence or two of user-facing detail.
Link relevant docs inline where they belong: [Docs](https://docs.clawker.dev/some-page).
Put docs links inline in the bullet next to the change they describe. HTML comment lines are stripped from the rendered body, so a metadata comment would be silently dropped — don't add one.
One source, two surfaces. The same CHANGELOG.md feeds a
show-once-on-upgrade teaser (printed on the first interactive run after an
upgrade — except the first changelog-aware run, which seeds last_seen_changelog
to the current version and shows nothing, with no catch-up backfill) and the
curated header at the top of the GitHub release notes. The CLI
does not embed the file —
it fetches the raw CHANGELOG.md from main over the network at runtime (the
CLI runs on the host and is always online). GitHub release notes are currently
produced by GoReleaser's auto changelog groups (not extracted from CHANGELOG.md
in CI yet). There is no second source to keep in sync.
PR Processs
- Fork the repository
- Create a feature branch from
main - Make your changes with tests
- Ensure
make testpasses - Open a PR against
main - Describe what changed and why in the PR description
PRs are reviewed by the maintainer. Expect feedback within a few days. For larger changes, open an issue first to discuss the approach.
Architecture
Before making significant changes, familiarize yourself with the codebase:
- docs/architecture.mdx — System layers, package DAG, key abstractions
- docs/design.mdx — Design philosophy, security model, core concepts
- docs/testing.md — Test strategy, patterns, and how to write tests
- docs/cli-reference/ — Auto-generated CLI command docs
Package-specific docs live in internal/*/CLAUDE.md files.
Issue Labels
| Label | Description |
|---|---|
bug | Bug reports |
enhancement | Feature requests |
good first issue | Beginner-friendly tasks |
known-issue | Known bugs or limitations |
roadmap | Planned features |
Code of Conduct
Please read and follow our Code of Conduct. Be kind, be constructive, be welcoming.
License & Contributor Agreement
Clawker is dual-licensed: AGPL-3.0-or-later for everyone, with commercial licenses available from the maintainer. So that contributions can ship under both, this project uses a Contributor License Agreement: you keep copyright of your work, your contribution is published under the AGPL-3.0-or-later, and you grant the maintainer the right to also license it under commercial terms.
One subproject is the exception: the clawker-support plugin, tracked as the
clawker-plugin/ git submodule (schmitthub/clawker-plugin),
is licensed separately under the MIT License (see its LICENSE file).
Read the full text in CLA.md. On your first pull request, a CLA assistant asks you to sign by commenting a short confirmation phrase; merging is gated until you do.