Instruction file imported from IvanWng97/pixtuoid (
.github/instructions/rust.instructions.md). Copyright stays with the author.
Rust standards — pixtuoid
These apply to all Rust in this Cargo workspace. The authoritative source is the
root CLAUDE.md and the nested crates/*/CLAUDE.md — read those for the
architecture invariants. Many things that look like a bug are documented,
load-bearing design — read the item's own doc comment. This file is the
condensed coding-standard slice.
Errors & panics
- No
unwrap()/expect()in non-test code. Tests may unwrap freely. - App/binary code propagates errors via
anyhow::Result. Core (pixtuoid-core) reaches forthiserroronly when a typed error becomes load-bearing. - The hook listener and JSONL watcher log and continue on malformed input — they never panic.
- The hook shim must always exit 0 silently on any error — blocking Claude Code breaks the user's primary workflow. The 200 ms write timeout is non-negotiable.
Crate boundaries (load-bearing)
pixtuoid-coreandpixtuoid-scenehave no terminal/window dependencies — never addratatui,crossterm,winit,softbuffer, orstdout/println!there (the crate boundary +just archenforce it). Terminal/window code lives only in thepixtuoidbinary's painters over the engine's render seam (pixtuoid_scene::floor::render_floor/pixel_painter::render_to_rgb_buffer). There is no core render trait.- Events flow through one channel typed
mpsc::Sender<(Transport, AgentEvent)>. Don't hardcodeTransport::Hookon the consumer side — eachSourcetags its own events. - The
Sourcetrait is the only seam for adding agent CLIs. Don't bypass it.
Logging
- Use
tracing::{info, warn, error}— notprintln!/eprintln!. The only exceptions are the headless summary and explicit user-facing CLI output.
Tests (TDD-first)
- Write the failing test before the implementation. Don't add code without a test that exercises it.
- Unit tests:
#[cfg(test)] mod testsnext to the code, or a siblingtests.rsdeclared#[cfg(test)] mod tests;for large modules (keeps production readable without widening the API). - Integration / public-contract tests live in
crates/<crate>/tests/*.rs(they see only thepubAPI). - Run the suite with
just test(nextest). Scope withcargo nextest run -p <crate> <filter>while iterating. Don't chaincargo clippy && cargo test— they use separate build caches, so chaining recompiles the workspace twice. Runjust preflightor one check at a time.
Style
- Comments explain WHY, not what — only where a reader can't tell from the code (a workaround, a non-obvious constraint, a surprising invariant).
- DRY, YAGNI — no features beyond the current scope.
- Match the surrounding code's naming, idiom, and comment density.
- Keep docs current — a change to module structure, the public API, or a
developer workflow updates the relevant
CLAUDE.md/README.mdin the same commit. - Verify locally with
just preflight(lint → clippy → hack → test, the exact CI order) before pushing.