Purpose: Guide for contributing to CueLoop, covering development workflow, standards, and submission process.
Thank you for your interest in contributing to CueLoop! This document provides guidelines for contributing effectively.
- Rust (toolchain pinned via
rust-toolchain.toml) - GNU Make >= 4 (
makeon Linux,gmakeon many macOS setups) - Git
# Clone the repository
git clone https://github.com/fitchmultz/cueloop
cd cueloop
# Install locally
make installThis installs the cueloop binary to ~/.local/bin/cueloop (or a writable fallback).
macOS note: install GNU Make with
brew install makeand usegmake ...unless your PATH already pointsmaketo Homebrew gnubin.
A low-risk first contribution loop:
# 1) Read orientation docs
# (README + docs/index.md)
# 2) Create a focused branch
git checkout -b RQ-XXXX-first-contribution
# 3) Make one small change + tests/docs
# 4) Run local gate
make agent-ci
# 5) Open a PR with verification notesFor docs-only work, still run make agent-ci; it now routes to the lighter ci-docs safety gate when no executable surface changed.
During development, you can use these commands for rapid iteration:
# Run tests for the cueloop crate
cargo test -p cueloop
# Run the CLI locally
cargo run -p cueloop -- <command>
# Validate the queue format
cargo run -p cueloop -- queue validate
# List queue contents
cargo run -p cueloop -- queue list
# Generate rustdocs for API review
make docsAll contributions MUST pass make agent-ci before being considered complete. This is a hard requirement.
make agent-ci is the only CI command most contributors should need to think about. It is the required pre-commit gate and it chooses the right underlying tier for the current uncommitted diff.
make agent-ci behavior (see docs/guides/ci-strategy.md for the full matrix and lower-level tiers):
- It inspects only the current uncommitted local diff (unstaged + staged + untracked files), not earlier commits already on the branch.
- With no local changes, it exits successfully without running a CI target.
- Docs/community-only changes:
make ci-docs - Ancillary non-docs changes (not
crates/**and not macOS ship surface):make ci-fast - Rust crate changes (
crates/**),mk/rust.mkedits, release/build script changes, andMakefileedits that touch Rust release/build/install targets:make ci(release-shaped Rust gate) - App bundle, schemas, macOS/Xcode bundling scripts, toolchain changes, and
Makefileormk/macos.mkedits that touch macOS build/test targets:make macos-ci
Makefile and scripts/** are not blanket macOS triggers anymore. CI/router-only edits (for example scripts/agent-ci-surface.sh, scripts/lib/release_policy.sh, or agent-ci target wiring in Makefile) should stay below the Mac app gate.
Merge safety: tier ci does not run Xcode or Swift tests. Before merging work that could affect the mac app, run make macos-ci or CUELOOP_AGENT_CI_MIN_TIER=macos-ci make agent-ci at least once.
Lower-level gate reference (mostly implementation detail / power-user material):
Docs-only gate (ci-docs) pipeline:
check-env-safety → check-backup-artifacts → check-file-size-limits → docs/community scan
Fast gate (ci-fast) pipeline:
check-env-safety → check-backup-artifacts → check-file-size-limits → rust-toolchain-check → version-check → format-check → lint → test
Full Rust release gate (ci) adds:
build → generate → install-verify
Canonical full make ci pipeline:
check-env-safety → check-backup-artifacts → check-file-size-limits → rust-toolchain-check → version-check → format-check → lint → test → build → generate → install-verify
Optional cold or offline prep: make deps runs cargo fetch --locked after toolchain/version checks; it is not part of the default ci-fast / ci graphs.
make updaterunscargo updateand refreshesCargo.lockto the latest versions compatible with existingCargo.tomlrequirements. Bumping minimum versions of direct dependencies is still an explicit manifest edit; the target does not rewrite requirement ranges for you.- After lockfile refreshes, run the routed gate (
make agent-ci) and considermake security-auditfor release-facing work (seeAGENTS.md).
Run required gate with:
make agent-ci
# Optional (shared workstation): CUELOOP_CI_JOBS=4 make agent-ci
# Optional (raise floor): CUELOOP_AGENT_CI_MIN_TIER=macos-ci make agent-ci
# Optional (force a fresh Xcode build tree): CUELOOP_XCODE_CLEAN_DERIVED_DATA=1 make macos-ciDo not commit or push changes if make agent-ci is failing. Fix all issues first.
For quick local verification before a full CI run:
make pre-commitThis runs environment safety checks, backup-artifact checks, and formatting validation.
For public-release verification:
make release-verify VERSION=<x.y.z>
make pre-public-check
# Optional (shared workstation): CUELOOP_CI_JOBS=4 CUELOOP_XCODE_JOBS=4 make pre-public-checkmake release-verify is the full release preflight. It also deliberately tolerates an already-existing local v<version> tag during the local release verification phase so shipped releases can be revalidated without hand-editing tag state.
We follow standard Rust conventions with additional project-specific requirements:
- Formatting:
cargo fmt(enforced by CI) - Linting:
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings(warnings treated as errors;make lintis the supported entrypoint) - Visibility: Default to private; prefer
pub(crate)overpubunless cross-crate use is required - Errors: Use descriptive error types (
thiserror) andResult<T, E>over panics - Cohesion: Keep modules/files focused; split large files rather than growing grab-bags
Every new or changed source file MUST start with a module doc comment that states:
- What the file is responsible for
- What it explicitly does NOT handle
- Any invariants/assumptions callers must respect
In Rust, prefer //! module docs at the top of the file:
//! Task queue management.
//!
//! Responsibility: Reading, writing, and validating the queue JSON file.
//! Does NOT handle: Task execution (see runner module) or git operations.
//! Invariants: Queue file must be valid JSON matching the queue schema.
All new or changed behavior must be covered by tests:
- Success modes: Normal operation paths
- Failure modes: Error handling and edge cases
- Location: Prefer tests near the code via
#[cfg(test)] - Integration tests: Use
crates/cueloop/tests/for cross-module behavior - Agent CI classifier: If you change
scripts/agent-ci-surface.shor path allowlists inscripts/lib/release_policy.sh, extendcrates/cueloop/tests/agent_ci_surface_contract_test.rsso representativenoop/ci-docs/ci-fast/ci/macos-cirouting stays pinned (seedocs/guides/ci-strategy.md).
Example:
# Run all tests (nextest workspace tests with cargo-test fallback, then doc tests)
make test
# Run tests for just the cueloop crate
cargo test -p cueloopCueLoop uses cargo-llvm-cov for code coverage analysis. Coverage is optional and not part of the default CI gate.
# Install cargo-llvm-cov
cargo install cargo-llvm-cov --locked
# On macOS, you may also need the llvm-tools component
rustup component add llvm-tools-preview# Generate coverage report
make coverage
# Clean coverage artifacts
make coverage-cleanThe coverage target generates:
- HTML Report:
target/coverage/html/index.html—make coverageechoes this path when the run finishes; open it manually in a browser. The Makefile does not launch a platform viewer, which keeps Linux and headless environments predictable (seemk/coverage.mkanddocs/guides/ci-strategy.md). - JSON Data:
target/coverage/coverage.json(machine-readable coverage data)
The HTML report shows:
- Line-by-line coverage highlighting
- Per-file coverage percentages
- Per-crate breakdown
The terminal output shows:
- Total coverage (lines, functions, regions)
- Per-crate breakdown (sorted alphabetically)
Coverage helps identify untested code paths but does not replace thoughtful test design.
For troubleshooting coverage issues, see Troubleshooting.
CueLoop's CLI is a user-facing contract. For cross-module behaviors (argument parsing → filesystem IO → queue mutation → output),
prefer integration tests in crates/cueloop/tests/.
Use crates/cueloop/tests/test_support.rs helpers to avoid repeating boilerplate:
temp_dir_outside_repo()to isolate stategit_init(dir)andcueloop_init(dir)to create a valid reporun_in_dir(dir, args)to execute the compiledcueloopbinarywrite_queue(...)/write_done(...)andread_queue()/read_done()to set fixtures and assert results
Example skeleton:
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path())?;
test_support::cueloop_init(dir.path())?;
test_support::write_queue(dir.path(), &tasks)?;
let (status, stdout, stderr) = test_support::run_in_dir(dir.path(), &["queue", "archive"]);
anyhow::ensure!(status.success(), "...\nstdout:\n{stdout}\nstderr:\n{stderr}");
let queue = test_support::read_queue(dir.path())?;For human-readable outputs that should remain stable (e.g., queue graph, queue burndown), we use insta snapshots.
Tests bind stable settings via test_support::with_insta_settings(...), which normalizes newlines, strips ANSI, and replaces
date strings with <DATE> to prevent daily churn.
To update snapshots after an intentional output change:
INSTA_UPDATE=always cargo test -p cueloopCommit the updated snapshot files under crates/cueloop/tests/snapshots/.
- Always run
cueloop initwith--non-interactivein tests. - Prefer state assertions (queue/done JSON) for mutation commands.
- If a CLI output order is nondeterministic, fix determinism in the renderer (preferred) or strengthen snapshot filters (fallback).
When changing user-visible workflows, maintain parity between the CLI and the macOS app, or document/justify the divergence explicitly.
User-facing commands and flags MUST have --help text with examples. Keep docs/cli.md in sync with changes.
Verify help text before committing:
cargo run -p cueloop -- <command> --helpPreferred format: RQ-####: <short summary>
Where #### is the task ID from .cueloop/queue.json.
If no task ID exists (for example, first external contribution), use:
chore: <short summary>fix: <short summary>docs: <short summary>
Examples:
RQ-0042: Add CI schema validationRQ-0007: Fix queue archive race conditiondocs: clarify run-loop troubleshooting step
Include in your PR description:
- What changed: A brief summary of the changes
- How to verify: Steps to validate (expected:
make agent-ci) - Breaking changes: Call out any breaking behavior explicitly
Example:
## Summary
Added validation for task ID format in queue operations.
## Verification
```bash
make agent-ci
```
## Breaking Changes
None.This repository is local-CI-first. We avoid adding remote CI (e.g., GitHub Actions) as a substitute for make agent-ci. The local CI gate is the source of truth.
Narrow exception: a small GitHub-hosted readiness workflow may exist when it is explicitly coordinating demo automation sequencing rather than replacing validation. The current example is Cursor Finish Line Ready, which waits for selected Cursor Automation checks, keeps one readiness check updated for visibility, and applies the cursor-finish-line-ready PR label for the downstream PR Finish Line automation. It is orchestration glue only, not canonical CI.
Before opening broad public visibility, run the dedicated checklist:
At minimum:
git status --short
git log --oneline -n 40
make agent-ciIf app changes are included in the release branch:
make macos-ci
# Optional caps while multitasking: CUELOOP_CI_JOBS=4 CUELOOP_XCODE_JOBS=4 make macos-ciKey locations to know:
apps/CueLoopMac/: macOS SwiftUI app (thin client that shells out to the bundledcueloopCLI)crates/cueloop/: Primary Rust CLI cratesrc/: CLI commands, runner integration, queue managementassets/prompts/: Embedded prompt templates
docs/: CLI + workflow + configuration docs (docs/index.mdis the entry point)schemas/: Generated JSON schemas (committed).cueloop/: Repo-local runtime statequeue.jsonc(.jsonfallback): Active tasks (source of truth)done.jsonc(.jsonfallback): Archived tasksconfig.jsonc(.jsonfallback): Project config (overrides global)
- Fast-path guidelines: See AGENTS.md for quick reference
- Detailed documentation: See docs/index.md
- Workflow details: See docs/workflow.md
- Configuration: See docs/configuration.md
- Security: See SECURITY.md
If you have questions not covered here:
- Check the existing documentation in
docs/ - Review AGENTS.md for contributor expectations
- Open an issue for discussion before investing significant effort
By contributing to CueLoop, you agree that your contributions are licensed under the project's MIT License.
Thank you for contributing to CueLoop!