Contributing to quokka
June 1, 2026 · View on GitHub
Thanks for considering a contribution! This guide covers the practical bits. For the why behind the design, read docs/ARCHITECTURE.md first — it explains the one structural rule that keeps quokka testable.
By participating you agree to abide by the Code of Conduct.
Ways to help
- Report a bug or request a feature — use the issue templates. Please check the README's "What it does NOT do" section first; some requests are intentionally out of scope because iOS makes them impossible.
- Pick up an issue — anything labelled
good first issueis a self-contained starting point. Comment on it so we don't duplicate work. - Improve docs — corrections to the README, this guide, or
ARCHITECTURE.mdare always welcome and review fast.
Project layout
src/
├── lib.rs # run() — shared entry point: clap parsing + dispatch
├── bin/
│ ├── quokka.rs # primary binary — a thin shim over run()
│ └── qk.rs # short alias — intentionally identical to quokka.rs
├── device/
│ ├── mod.rs # the Device trait, FakeDevice, and the real impl
│ └── model_names.rs # ProductType → marketing-name lookup
├── ui.rs # terminal output helpers shared by every command
└── commands/
├── mod.rs
├── status.rs # `quokka status`
├── apps.rs # `quokka apps` — list / uninstall (ratatui picker)
├── analyze.rs # `quokka analyze` — heaviest files (ratatui picker)
├── dashboard.rs # pure dashboard renderer (used by status + launcher)
└── menu.rs # interactive launcher shown for a bare `quokka`
tests/
├── integration.rs # commands exercised against a fake Device — no iPhone
├── e2e_smoke.rs # real device, behind the `e2e` feature
└── e2e_enrich_bench.rs # perf sweep, behind `e2e`, #[ignore] by default
docs/
├── ARCHITECTURE.md # how it all fits together, and the design rules
└── superpowers/specs/ # design specs for individual commands
The Device trait in src/device/mod.rs is the seam that makes quokka
testable. The real implementation talks to the idevice crate; tests inject
a FakeDevice. Please keep that seam clean — no idevice type may leak
through it. See ARCHITECTURE.md for the full reasoning.
Building
cargo build
The repo pins the stable toolchain via rust-toolchain.toml — several
dependencies require edition2024. Don't change the pin without checking.
Running tests
quokka has three test layers. The first two are the regression net — CI runs them on every push and pull request, so a change that breaks the current behaviour fails before it can merge.
- Unit tests (
#[cfg(test)]modules next to the code) cover pure logic: byte formatting, sorting, the dashboard renderer, battery-health heuristics. They never touch hardware. - Integration tests in
tests/integration.rsexercise whole commands against aFakeDevice, so they run without an iPhone connected. - End-to-end tests live behind the
e2efeature flag. They drive the realidevicebackend against a physical iPhone over USB and are never run in CI — run them yourself when touchingdevice/mod.rs's real path.
cargo test # layers 1 + 2 — what CI runs
cargo test --features e2e # layers 1 + 2 + 3 — needs an iPhone, plugged in and trusted
cargo test --features e2e-android # Android layer — needs an Android device over adb
cargo test --test integration # just the integration file
cargo test -- format_bytes # filter by test-name substring
When you add or change logic, write its unit and/or integration tests in the same change — not in a follow-up. A pull request that changes behaviour without a test that would have caught the old behaviour will be asked for one. This is how we keep regressions out: the test you add today is what fails the day someone else's change breaks your feature.
Style and checks
cargo fmt
cargo clippy --all-targets -- -D warnings
Both are enforced by CI. There is also a local PostToolUse hook in
.claude/settings.json that runs fmt + clippy + test automatically after
Rust edits made through Claude Code — but always run them yourself before
pushing if you edit by hand.
Commits and pull requests
- Keep commits focused; messages should explain why, not just what.
- Open pull requests against
main. Small PRs review faster than big ones. - Fill in the pull request template, including the testing checklist.
- If you change any command's output, include a transcript or screenshot in the PR description — UX is reviewed, not just code.
- CI must be green before a PR is merged.
Bumping the idevice dependency
The idevice crate ships breaking changes at nearly every point release until
it reaches 0.2.0, so Cargo.toml pins it with =. When you bump it:
- Re-do the API research first — the
tools/src/directory of the upstream repo is the canonical example of current usage. - Update only the
mod realsubmodule insrc/device/mod.rsto match. TheDevicetrait and everything above it should not need to change — if they do, the seam has sprung a leak; fix that instead. - Run
cargo test --features e2eagainst a real device before opening the PR.