Working notes for agents and contributors on QuickRunner (qr).
- Build:
cargo build --release(binary attarget/release/qr) - Test:
cargo test - Install locally:
cargo install --path .
- Toolchain: The crate is edition 2024 (
rust-version = "1.85"). The base VM image ships an older default (rustc 1.83), which cannot build this crate. The startup update script installs and defaults thestabletoolchain (rustup default stable) withrustfmt+clippy, so a fresh shell already has a workingcargo. If you ever see edition-2024 build errors, runrustc --versionandrustup default stable. - Lint (matches
.github/workflows/ci.yml):cargo fmt --all -- --checkandcargo clippy --all-targets --locked -- -D warnings. - No services to run.
qris a fully self-contained local CLI — no DB server, web server, or network dependency is required. Persistence is a local SQLite file (bundledrusqlite) plus JSON caches;cargo testmocks the AI HTTP layer, so no API key is needed for the suite. - Isolated manual testing: every config key is overridable via
QR_*env vars, so you can exercise the tool without touching the real user config. Useful ones:QR_PROJECT_ROOTS(colon-separated),QR_SCAN_DEPTH,QR_STATS_ENABLED=true,QR_STATS_DB_PATH=/tmp/…. A quick end-to-end smoke test:qr scan→qr go --print-path <name>→qr stats. - Test fixtures (environment-provided, not in the repo): four dependency-free LeetCode-easy
sample projects (Rust / Node / Python / Go), one per language
qr learndetects, live at$HOME/qr-test-projectson the VM. They are seeded by$HOME/.local/bin/qr-seed-test-projects(idempotent), which the startup update script runs. Point QuickRunner at them withexport QR_PROJECT_ROOTS="$HOME/qr-test-projects"to exercisescan,go,run, andlearnagainst real projects. If they are ever missing, regenerate withqr-seed-test-projects. - Gotcha —
qr goneeds a TTY for ambiguous matches: in a non-interactive shell, a query that matches multiple projects errors withMultiple matches for '<q>'instead of showing the picker. Use a unique substring (or--print-path) when scripting. - AI (
qr do) is the only command that makes a live model call (qr learnis static marker-based detection and needs no key). It resolves the API key from the protocol's well-known env var (OPENAI_API_KEY/ANTHROPIC_API_KEY), thenconfig.toml, then the OS keychain — so exportingOPENAI_API_KEYis enough to authenticate. Point it at a specific model/endpoint withQR_AI_MODELandQR_AI_BASE_URL(there is noOPENAI_MODEL/OPENAI_BASE_URLmapping — map those yourself).qr doprints the AI-suggested command and only runs it after you typey(default is No), so it is safe to pipenfor a non-executing smoke test. None of this is required for build, lint, tests, or scan/go/stats. - Gotcha — AI fallback provider: the default config does not define an
[ai.fallback]. If you configure one manually,qrrefuses to retry prompt context against a different protocol/base URL unlessQR_AI_ALLOW_CROSS_ENDPOINT_FALLBACK=trueis set. When using a proxy/gateway and you want automatic fallback, keep the fallback endpoint on the same base URL or opt in explicitly. - Gotcha — secrets in the Desktop terminal: injected secret env vars are present in the agent
shell but a freshly opened Desktop GUI terminal may not inherit them. To drive an AI demo from the
Desktop, write the needed vars to a temp file the agent shell can produce and
sourceit in the Desktop shell (then delete it) — do not print secret values or commit them.
src/stats_db.rs creates the command_runs table with CREATE TABLE IF NOT EXISTS
and there is intentionally no migration scaffolding yet — only one schema version
has ever shipped, so none is needed.
The first time you change the command_runs schema (add / rename / drop a column),
you must add migration support in the same change. CREATE TABLE IF NOT EXISTS does
nothing when the table already exists, so an existing user's database keeps the old
columns and the next INSERT/SELECT referencing a new column fails with
no such column, breaking every stats write. Add a PRAGMA user_version check on open
and run ordered ALTER TABLE / migration steps to upgrade older databases.
Until then, leave it as-is — don't add the scaffolding before there's a schema change that needs it.