watchexec/cargo-watch
Watches over your Cargo project's source.
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓10 active contributors
- ✓CC0-1.0 licensed
- ✓CI configured
Show all 6 evidence items →Show less
- ✓Tests present
- ⚠Stale — last commit 1y ago
- ⚠Concentrated ownership — top contributor handles 78% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/watchexec/cargo-watch)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/watchexec/cargo-watch on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: watchexec/cargo-watch
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/watchexec/cargo-watch shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 10 active contributors
- CC0-1.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 1y ago
- ⚠ Concentrated ownership — top contributor handles 78% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live watchexec/cargo-watch
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/watchexec/cargo-watch.
What it runs against: a local clone of watchexec/cargo-watch — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in watchexec/cargo-watch | Confirms the artifact applies here, not a fork |
| 2 | License is still CC0-1.0 | Catches relicense before you depend on it |
| 3 | Default branch 8.x exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 509 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of watchexec/cargo-watch. If you don't
# have one yet, run these first:
#
# git clone https://github.com/watchexec/cargo-watch.git
# cd cargo-watch
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of watchexec/cargo-watch and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "watchexec/cargo-watch(\\.git)?\\b" \\
&& ok "origin remote is watchexec/cargo-watch" \\
|| miss "origin remote is not watchexec/cargo-watch (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(CC0-1\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"CC0-1\\.0\"" package.json 2>/dev/null) \\
&& ok "license is CC0-1.0" \\
|| miss "license drift — was CC0-1.0 at generation time"
# 3. Default branch
git rev-parse --verify 8.x >/dev/null 2>&1 \\
&& ok "default branch 8.x exists" \\
|| miss "default branch 8.x no longer exists"
# 4. Critical files exist
test -f "src/main.rs" \\
&& ok "src/main.rs" \\
|| miss "missing critical file: src/main.rs"
test -f "src/watch.rs" \\
&& ok "src/watch.rs" \\
|| miss "missing critical file: src/watch.rs"
test -f "src/args.rs" \\
&& ok "src/args.rs" \\
|| miss "missing critical file: src/args.rs"
test -f "src/options.rs" \\
&& ok "src/options.rs" \\
|| miss "missing critical file: src/options.rs"
test -f "src/rustc.rs" \\
&& ok "src/rustc.rs" \\
|| miss "missing critical file: src/rustc.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 509 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~479d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/watchexec/cargo-watch"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
cargo-watch is a command-line tool that monitors your Rust project's source code for changes and automatically re-runs Cargo commands (like cargo check, cargo test, cargo build) whenever files are modified. It wraps the watchexec library (v1.17.2) and integrates with cargo_metadata to provide intelligent file filtering and build awareness specific to Cargo projects. Single-binary architecture: src/main.rs is the entry point, src/args.rs and src/options.rs parse CLI arguments via clap v2, src/watch.rs contains the core watch loop using the watchexec library, src/rustc.rs handles Rust compiler output parsing, and src/root.rs manages the Cargo project root detection. The binary is built from [[bin]] section in Cargo.toml targeting a single cargo-watch executable.
👥Who it's for
Rust developers who want faster feedback loops during active development—similar to how nodemon or guard work in Node.js and Ruby. Developers who repeatedly run cargo check or cargo test during coding sessions benefit most from the automatic re-invocation without manual shell commands.
🌱Maturity & risk
This project is on life support and not actively developed. The maintainer (@passcod) explicitly states in the README that Cargo Watch will not receive updates but remains available. No recent commits are visible in the file structure, the test suite exists (tests/ with insta snapshots), and CI is configured (check.yml), but the project is superseded by Bacon and Watchexec for new features. It is production-ready but stagnant.
Single-maintainer abandonment risk is extremely high—the README explicitly acknowledges the project is on life support with no planned updates. Dependency count is moderate (watchexec, cargo_metadata, clap 2.34.0 which is quite old, dotenvy, notify-rust), and clap v2 is unmaintained (v4 is current). No breaking changes are expected, but security updates to dependencies may lag. If you depend on this for critical workflows, plan to migrate to Bacon or Watchexec.
Active areas of work
No active development is occurring. The project is frozen at version 8.5.3. The maintainer recommends users migrate to Bacon instead. The GitHub workflows (release.yml, check.yml) are configured but likely dormant. No open PRs or new commits are implied by the file structure.
🚀Get running
git clone https://github.com/watchexec/cargo-watch.git
cd cargo-watch
cargo build --release
cargo run -- -x test
Daily commands:
cargo watch -x check
cargo watch -x test
cargo watch -c -x build
Run cargo watch --help for all options. The tool runs the Cargo subcommand specified after -x whenever watched files change.
🗺️Map of the codebase
src/main.rs— Entry point that orchestrates argument parsing, logging setup, and the main watch loop—all contributors must understand the execution flow.src/watch.rs— Core watch loop logic that binds to watchexec library and handles file change events; critical for understanding how cargo commands are triggered.src/args.rs— Command-line argument definitions using clap; essential for understanding the CLI surface and what features are exposed.src/options.rs— Conversion from clap args to internal Options struct; bridges CLI layer with application logic.src/rustc.rs— Handles rustc output parsing and error filtering; critical for the core feature of watching Cargo builds.Cargo.toml— Dependency manifest including watchexec, cargo_metadata, and notify-rust; defines the external integrations.
🧩Components & responsibilities
- CLI Parser (args.rs + options.rs) (clap, dotenvy (.env support)) — Validates user input, applies defaults, converts clap structs to internal Options.
- Failure mode: Invalid flags or missing required args → early error and help text; invalid UTF-8 paths → panic.
- Watch Loop (watch.rs) (watchexec, cargo_metadata, std::process) — Owns the main event loop; detects FS changes, filters by ignore rules, spawns cargo commands.
- Failure mode: Cargo command fails → output printed; watchexec crashes → whole process exits; killed child process → retries on next event.
- Rustc Output Parser (rustc.rs) (regex, serde_json (implicit)) — Parses JSON or plain text compiler diagnostics; extracts errors and warnings for display.
- Failure mode: Malformed rustc output → falls back to raw echo; parsing errors → logged but not fatal.
- Project Root Detection (root.rs) (cargo_metadata, camino (UTF-8 paths)) — Finds Cargo.toml and workspace structure; determines which paths to watch.
- Failure mode: No Cargo.toml found → error and exit; workspace misconfigured → may watch wrong paths.
- Notifications (notify-rust integration) (notify-rust, dbus (Linux) / NSUserNotificationCenter (macOS)) — Optional desktop alert on build completion (especially failures).
- Failure mode: Notification daemon unavailable → silently skipped; no impact on watch loop.
🔀Data flow
File System→watchexec— FS events (inotify/FSEvents/ReadDirectoryChangesW) → watchexec debounces and filters by ignore ruleswatchexec→Watch Loop— Debounced change notification triggers cargo command executionWatch Loop→Cargo Process— Spawns child process with cargo command (check/test/build) and inherits stdioCargo Process→Rustc Output Parser— Compiler output streamed to parser; errors/warnings extracted and re-formattedRustc Output Parser→Terminal / Desktop Notification— Formatted diagnostics printed to stderr/stdout; optional desktop alert sentcargo_metadata→Watch Loop— Project structure (workspaces, source dirs) determines which paths to monitor
🛠️How to make changes
Add a new cargo-watch CLI flag
- Define the new argument struct field in the Opt struct with clap attributes (
src/args.rs) - Add corresponding field to Options struct and implement conversion logic from Opt (
src/options.rs) - Use the new option in the watch loop or command building logic (
src/watch.rs) - Add integration tests if the flag affects user-visible behavior (
tests/echo.rs)
Enhance rustc output parsing for new diagnostics
- Add pattern matching or parsing logic to handle new compiler output format (
src/rustc.rs) - Test the new parsing with snapshot tests if output formatting changes (
tests/snapshots)
Modify the watch loop behavior or command execution
- Implement the new behavior in the main watch event handler (
src/watch.rs) - Update Options struct if new configuration is needed (
src/options.rs) - Add an exec test to verify the new behavior (
tests/exec.rs)
🔧Why these technologies
- watchexec — Battle-tested file-watching library that handles cross-platform FS events, debouncing, and ignore patterns (gitignore, custom filters).
- cargo_metadata — Provides structured access to Cargo workspace and package metadata without parsing JSON manually.
- clap 2.x — Lightweight CLI argument parser; clap 2 chosen for stability over newer 3.x/4.x (backward compatibility during maintenance mode).
- notify-rust — Desktop notifications (optional); alerts user to build failures without requiring terminal focus.
- stderrlog & log — Structured logging with verbosity control; keeps internal debug info separate from watched command output.
⚖️Trade-offs already made
-
Watches Cargo.toml + src/, not arbitrary paths
- Why: Simplifies logic and aligns with typical Rust project structure.
- Consequence: Users cannot easily watch non-source files (e.g., assets) without custom shell commands.
-
Runs cargo commands sequentially, not in parallel
- Why: Avoids resource contention and keeps output clear and readable.
- Consequence: Slow commands (e.g., full
cargo test) will delay subsequent triggers.
-
Maintenance mode: no major feature additions
- Why: Author recommends Bacon or Watchexec as better alternatives.
- Consequence: Users seeking advanced features should migrate; cargo-watch remains stable but not cutting-edge.
🚫Non-goals (don't propose these)
- Does not provide IDE-level integration or LSP support
- Does not run commands in parallel or with concurrency control
- Does not persist build cache across machine restarts or CI systems
- Does not modify source code or apply automatic fixes; only re-runs cargo
- Does not support Windows subsystem details beyond watchexec's built-in support
⚠️Anti-patterns to avoid
- Blocking command execution in main loop (Medium) —
src/watch.rs: Cargo commands run synchronously, blocking the watch loop. Long-running tests will prevent new file-change events from being processed until completion. - Clap 2.x (obsolete version) —
Cargo.toml: clap 2.34.0 is end-of-life; project is in maintenance mode and cannot easily upgrade without breaking changes.
🪤Traps & gotchas
No environment setup required, but be aware: clap v2 has significantly different ergonomics than clap v4; migration would be substantial. The maintainer notes the project has 'four different syntaxes' for running commands, which implies legacy complexity in src/args.rs. The watchexec v1.17.2 dependency is somewhat dated (v2+ exists but not used). Tests use insta snapshots (tests/snapshots/*.snap files)—modifying output requires regenerating snapshots with insta review.
🏗️Architecture
💡Concepts to learn
- File system event notification (inotify/FSEvents) — cargo-watch's entire value proposition depends on efficiently detecting file changes via the watchexec library, which uses OS-native notification APIs (inotify on Linux, FSEvents on macOS, etc.); understanding this avoids polling filesystem constantly
- Cargo metadata integration — cargo_metadata 0.18.1 is used to query Cargo.toml, understand project structure, and identify which files to watch; modifying src/root.rs requires understanding this crate
- Rustc compiler output parsing (error/warning format) — src/rustc.rs parses the structured error output from
rustcto filter, format, and display compiler messages intelligently; this drives the user-facing formatting - Process spawning and signal handling — src/watch.rs spawns Cargo subprocesses and must handle signals (SIGINT, SIGTERM) gracefully; the watchexec crate abstracts this, but understanding process lifecycle is essential for debugging hangs or incomplete shutdowns
- Desktop notification integration (notify-rust) — notify-rust 4.7.0 sends system notifications (macOS/Linux) when builds complete; this is optional but affects user experience and requires understanding async event handling
- Snapshot testing with insta — The test suite uses insta 1.32.0 for snapshot-based regression testing (see tests/snapshots/*.snap); modifying output requires understanding snapshot approval workflow, not traditional assertions
🔗Related repos
watchexec/watchexec— The underlying library that cargo-watch wraps for file system notification and command execution; moving to this directly gives more control and modern featuresbacon-rs/bacon— Modern, actively maintained alternative recommended by the cargo-watch maintainer in the README; adds TUI, task files, and pager support that cargo-watch never gotrust-lang/cargo— Cargo itself; cargo-watch integrates via cargo_metadata 0.18.1 to understand project structure and invoke build commands correctlynotify-rs/notify— The file system notification library used transitively by watchexec; cargo-watch's performance and reliability depend on this crate's maturityclap-rs/clap— CLI argument parser (v2.34.0); cargo-watch's argument parsing and help text generation depend entirely on clap's definition in src/args.rs
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for watch.rs command execution and file watching behavior
The tests/ directory currently only has echo.rs and exec.rs tests with snapshots. The core watch.rs module lacks dedicated integration tests for file watching triggers, debouncing, and command execution chains. This would improve reliability and prevent regressions in the core watching mechanism.
- [ ] Create tests/watch.rs with integration tests for file modification detection
- [ ] Add test cases for debouncing behavior in tests/watch.rs
- [ ] Add test cases for multiple command execution in sequence in tests/watch.rs
- [ ] Create corresponding snapshot files in tests/snapshots/ for expected outputs
- [ ] Test interaction between src/watch.rs and src/args.rs argument parsing
Add shell completion tests and verification for zsh completions
The completions/zsh file exists but has no automated tests. Given that cargo-watch is installed via package managers and users rely on shell completions, this is a high-value gap. No test infrastructure exists to validate completion script syntax or coverage of CLI flags.
- [ ] Create tests/completions.rs to parse and validate zsh completion syntax
- [ ] Cross-reference completions/zsh against src/args.rs to ensure all flags are documented
- [ ] Add CI step in .github/workflows/check.yml to validate completion scripts
- [ ] Verify that new flags added to src/args.rs trigger completion updates
- [ ] Consider adding bash/fish completion tests in the same test file
Add tests for src/rustc.rs error parsing and output handling
The rustc.rs module handles compiler error parsing and formatting but has no dedicated tests. This is critical since incorrect parsing could cause watch to miss real compilation errors or crash on unexpected rustc output formats across different Rust versions.
- [ ] Create tests/rustc.rs with unit tests for error parsing functions in src/rustc.rs
- [ ] Add test cases for various rustc error formats (warnings, errors, notes)
- [ ] Test handling of multi-line error messages and stack traces
- [ ] Add snapshot tests in tests/snapshots/ for formatted error output
- [ ] Test compatibility with the MSRV (Rust 1.75.0) rustc output format
🌿Good first issues
- Add snapshot tests for src/rustc.rs error parsing: The file has parsing logic but tests/snapshots/ currently only covers echo and exec behavior. Add test cases for actual
rustcerror/warning output parsing to ensure the formatter handles edge cases.: medium - Document the 'four different syntaxes' mentioned in README: Audit src/args.rs to identify and document the multiple command syntaxes (e.g.,
-x, shell variants, etc.) in a new doc/SYNTAX.md file with examples. The README hints at this pain point but provides no clarity.: small - Add integration test for Cargo project detection: src/root.rs finds the Cargo project root, but there's no test in tests/ validating this behavior with nested or non-standard project layouts. Create tests/root.rs with test fixtures in tests/touchdata/.: medium
⭐Top contributors
Click to expand
Top contributors
- @passcod — 78 commits
- @dependabot[bot] — 14 commits
- @alex-pinkus — 1 commits
- @DenisGorbachev — 1 commits
- @pseyfert — 1 commits
📝Recent commits
Click to expand
Recent commits
58e792b— 8.5.3 (passcod)e50ab24— have i not suffered enough (passcod)ed0a943— use macos-latest (passcod)2673bba— use watchexec github (passcod)e0174d9— update snapshots (passcod)6c2431c— do not fail fast (passcod)01d3fd2— bump msrv (passcod)5d3cd7c— add instructions for pm2/systemd-run (passcod)2cfce3c— nope, do it here (passcod)080ab44— recommend watchexec too (passcod)
🔒Security observations
The cargo-watch codebase has a generally reasonable security posture for a command-line utility. The primary concern is the use of outdated clap dependency (2.34.0) which is no longer maintained. Secondary concerns include proper validation of user input before shell execution and appropriate restrictions on file system monitoring scope. The project uses legitimate security-focused dependencies (shell-escape, dotenvy for .env handling) but these should be paired with robust input validation. No hardcoded credentials, SQL injection risks, or Docker/infrastructure issues were identified in the provided files.
- Medium · Outdated clap Dependency —
Cargo.toml - dependencies section. The codebase uses clap version 2.34.0, which is significantly outdated. clap 2.x reached end-of-life and is no longer maintained. Current versions are clap 3.x and 4.x. Outdated dependencies may contain unpatched security vulnerabilities. Fix: Upgrade clap to the latest version (4.x). Review the migration guide at https://github.com/clap-rs/clap/blob/master/CHANGELOG.md and update code accordingly. - Low · Potential Command Injection via shell-escape —
src/ - likely in args.rs, options.rs, or watch.rs. The codebase uses shell-escape (0.1.5) to escape shell arguments. While this library exists for this purpose, the use of shell escaping indicates command execution. If user input is improperly validated before reaching shell-escape, injection attacks are possible. Fix: Ensure all user input from command-line arguments is properly validated before being passed to shell execution. Use allowlists where possible rather than escaping. Review how arguments are processed in src/args.rs and src/options.rs. - Low · Broad File System Watch Access —
src/watch.rs and watchexec dependency. The watchexec dependency (1.17.2) provides file system watching capabilities. The application watches the entire Cargo project source for changes. If not properly restricted, this could monitor sensitive files or trigger unintended operations on symlinks or special files. Fix: Verify that file watching is restricted to project source directories and excludes sensitive locations (.git, .env files, credentials). Implement symlink attack protection and validate watch paths. - Low · Desktop Notification Library Usage —
Cargo.toml - notify-rust dependency. The notify-rust dependency (4.7.0) sends desktop notifications. This could potentially be exploited to display misleading notifications to users if the build output or error messages are compromised. Fix: Ensure that notification content is sanitized and doesn't execute arbitrary code. Validate all content before passing to notify-rust.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.