Skip to content

feat: add --watch to build, test, and test solidity - #8721

Open
aelmanaa wants to merge 2 commits into
NomicFoundation:mainfrom
aelmanaa:feat/watch-mode
Open

aelmanaa wants to merge 2 commits into
NomicFoundation:mainfrom
aelmanaa:feat/watch-mode

Conversation

@aelmanaa

Copy link
Copy Markdown
Contributor
  • Because this PR includes a bug fix, relevant tests have been included.
  • Because this PR includes a new feature, the change was previously discussed on an Issue or with someone from the team.
  • I didn't do anything of this.

Closes #891.

This adds a watch mode to hardhat build, hardhat test, and hardhat test solidity. Each command gets a --watch (-w) flag. With it, Hardhat runs the command, then runs it again each time a source, a test, or the config file changes. #891 asks for this and has 12 👍. It is also one of the first things people coming from forge test --watch look for.

The feature wasn't discussed with the team first, so I'm happy to change the approach, the flag names, or where the code lives.

How it works

It is a new built-in plugin, builtin:watch, that overrides the three tasks to add these arguments:

Argument Tasks Default
--watch, -w build, test, test solidity off
--watch-delay build, test, test solidity 50 (ms)
--no-restart build, test, test solidity off
--run-all test, test solidity off

Without --watch, each override calls runSuper and nothing changes.

With --watch, the parent process doesn't run the task. It watches the files with chokidar, which is already a dependency of hardhat. For each run, it starts a new hardhat process with the same command line, minus the watch arguments. A new process per run means every run loads the current config, plugins, and sources, the same as typing the command again. Nothing is left cached between runs. Foundry does the same thing.

  • Watched paths: the sources, the test directories (only the Solidity ones for build and test solidity), and the config file. Paths that don't exist are skipped. The artifacts and cache directories, node_modules, and .git are ignored.
  • Which tests run: one changed test file runs that file. Several changed test files run everything. Any other change reruns the previous run's test files, or everything if there aren't any. A file counts as a test when a test runner claims it and it is inside one of the configured test directories. The directory check is there because the Node.js runner claims any file no other runner takes, the config file included. --run-all turns this off. Test files or --grep given on the command line are kept on every run.
  • Restart: a change during a run stops the run (SIGTERM, then SIGKILL after 5 seconds) and starts a new one, unless --no-restart is set.
  • Keys: a reruns everything. q, Ctrl-C, or Ctrl-D quits. Input is passed to the child while a run is in progress.
  • Output: after each run it prints [Command was successful, lasted 3.57s] (or the exit code), then Watching N paths (sources, tests, and config) for changes. Press "a" to rerun everything, "q" to quit..
  • Running one of the tasks from code with watch: true throws the new error HHE603 (WATCH_MODE_REQUIRES_CLI), because watch mode needs the command line it was started with.

Tests

  • Unit tests in packages/hardhat/test/internal/builtin-plugins/watch/ for argument handling, test file selection, the session state machine, the file watcher, and the task overrides (40 tests). I checked that they fail when the selection or restart logic is broken.
  • pnpm build, pnpm lint, and pnpm test pass in packages/hardhat (2922 passing) and packages/hardhat-errors (38 passing). node scripts/check-dependencies.ts passes.
  • I also ran each behaviour by hand in a pty against a sample project, next to forge test --watch 1.8.1 on an equivalent Foundry project: narrowing to the changed test, a contract edit, several files at once, a compile error and its fix, a restart during a slow run, --no-restart, a, q, Ctrl-C (exit 0 and no processes left behind), a TypeScript test, a config change, a deleted file, --run-all, --grep, build --watch, and test solidity --watch. Watch mode adds about 0.1 to 0.2 seconds per run.

Differences from Foundry

  • --watch-delay is in milliseconds. Foundry's is in seconds.
  • --watch takes no list of paths. The paths come from the config.
  • There is no --rerun-failed.
  • Narrowing to the changed file works for TypeScript tests as well as Solidity tests.

Docs: NomicFoundation/hardhat-website#314

🤖 Generated with Claude Code

aelmanaa and others added 2 commits October 18, 2026 00:45
Closes NomicFoundation#891

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Oct 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c9f915a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@nomicfoundation/hardhat-errors Patch
hardhat Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a "watch mode" to compile task

2 participants