Postguy
Contributing

Development

Toolchain, everyday commands, working rules and the CI gates.

Toolchain

  • Stable Rust 1.95 or newer. This is rust-version in the root Cargo.toml, the floor egui 0.36 needs. CI uses stable.
  • There is no WASM target and no craft-* dependency.
  • The only embedded font is Poppins, plus the default fonts that ship inside egui.

Everyday commands

cargo build -p postguy                    # desktop app
cargo run -p postguy -- --workspace DIR --control /tmp/postguy-control.json
                                          # opt-in control channel (loopback, fresh owner-only token)
cargo run -p postguy-cli -- run --script STEPS.json --root DIR   # engine harness
cargo run -p postguy-cli -- ui --control FILE inspect             # or command/set/screenshot
cargo xtask ci                            # fmt, clippy -D warnings, test, layers, assets, parity, deny
cargo xtask layers                        # dependency layering only
cargo xtask assets [--write]              # asset policy against ATTRIBUTION.toml (ATTRIBUTION.md regenerate)
cargo xtask parity [--partial|--json]     # parity checklist validation and progress
cargo xtask deny                          # licences/sources (delegates to cargo-deny when installed)
cargo xtask size [--skip-build]           # release binary sizes against the size budgets
cargo xtask bench [--check] [--debug]      # headless frame-time capture (10k tree, 10 MB Raw)
cargo xtask icons [--check]               # regenerate ui-egui/src/icons_gen.rs from assets/icons
cargo xtask logo [--check]                # rasterize assets/logo/postguy.svg into PNG sizes
cargo xtask fuzz --time 300 [--seed N]    # mutation fuzzing (registered targets)
cargo xtask screenshots [--out DIR]       # render review screenshots into target/screenshots/

Import a file and generate a snippet

Each postguy-cli call process starts with no workspace open. It fails with no workspace is open; call workspace_open first.

To import a file and generate a snippet, run the steps as one script. Tool arguments take ids, so use a collection id and request id you read from collection_list.

cargo run -p postguy-cli -- run --script steps.json --root DIR
[
  {"tool": "workspace_open", "args": {"path": "ws"}},
  {"tool": "import_file", "args": {"path": "collection.json"}},
  {"tool": "collection_list", "args": {}}
]

Then add a snippet_generate step with the ids from that output. See Automation tools for the argument list.

Working rules (short form; AGENTS.md is the law)

  • Use conventional commits (feat(http): follow redirects with cookie capture) and branch as <type>/<slug>. Commit only green states. main is the integration branch.
  • Scope builds and tests to the crates you touched (-p, -j 2, under a timeout). The full sweep is CI's job (cargo xtask ci), and CI runs it on every PR.
  • Build every feature in this order: engine API, then automation tool (with an end-to-end test), then UI. A feature without its tool is not done. See the automation README and Adding a feature.
  • Keep tests hermetic. Loopback servers live in postguy-testkit. Tests never touch the internet. Fuzz findings become synthetic regression tests that you see failing first.
  • Update the parity row of the feature you touched.
  • Verify UI changes in one of these ways:
    • Run cargo run -p postguy-ui-egui --example shot -- OUT.png dark.
    • Run cargo xtask screenshots.
    • Launch the app with --control and use postguy-cli ui.

    click, key and type are not emulated. See Known gaps.

Gates the CI bundle runs

cargo xtask ci runs these in order:

  1. fmt --check
  2. clippy --workspace --all-targets -D warnings
  3. test --workspace
  4. layers
  5. assets
  6. parity
  7. deny

clippy.toml allows unwrap, expect and panic in tests. It forbids egui's checkbox and radio draw paths in favour of our widgets.

Parallel agents

  • Use a separate CARGO_TARGET_DIR and a separate git worktree for each agent.
  • Ad-hoc spike crates opt out of the workspace with an empty [workspace] table in their manifest.
Copyright © 2026