Skip to content

perf(cli): skip npm install during update when lockfile is unchanged (#17268)#39397

Open
rodboev wants to merge 1 commit into
NousResearch:mainfrom
rodboev:pr/cli-skip-npm-unchanged
Open

perf(cli): skip npm install during update when lockfile is unchanged (#17268)#39397
rodboev wants to merge 1 commit into
NousResearch:mainfrom
rodboev:pr/cli-skip-npm-unchanged

Conversation

@rodboev

@rodboev rodboev commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Every hermes update unconditionally runs npm ci twice (root-only, then workspace), even when the lockfile hasn't changed since the last successful install. On slow or firewalled networks this adds 30-60+ seconds of dead time for Python-only or docs-only commits.

The fix hashes package-lock.json with SHA-256 after each successful install and stores the digest in a per-checkout cache file under the hermes root (~/.hermes/.npm_lock_hash_<project_key>). On subsequent updates, _update_node_dependencies() compares the current lockfile hash against the stored digest and skips both npm ci calls when they match. The codebase already uses this pattern for the desktop build (_compute_desktop_content_hash / _desktop_build_needed) and the TUI install path (_tui_need_npm_install compares lockfile content).

The cache is keyed by PROJECT_ROOT so parallel worktrees don't collide, and validates that node_modules/ exists before skipping (a matching hash with missing node_modules forces a reinstall). All cache I/O is wrapped in try/except so a corrupt or inaccessible cache file never breaks the update path.

Changes

  • hermes_cli/main.py: add _npm_lockfile_changed() and _record_npm_lockfile_hash() helpers using hashlib.sha256; guard _update_node_dependencies() with an early return when the lockfile matches the stored hash; record hash after successful install (~+35 lines)
  • tests/hermes_cli/test_cmd_update.py: add 7 tests for the hash helpers, skip path, missing node_modules, and cache error handling (~+65 lines)

Validation

Scenario Before After
First update after install (no cache) runs npm ci (2x) runs npm ci (2x), records hash
Subsequent update, lockfile unchanged runs npm ci (2x), ~30-60s skips npm ci, logs "unchanged"
Subsequent update, lockfile changed runs npm ci (2x) runs npm ci (2x), updates hash
package-lock.json missing runs npm install fallback runs npm install fallback (unchanged)
node_modules/ deleted after cache written skips npm ci (broken) forces npm ci (node_modules check)
Cache file corrupt or inaccessible N/A (no cache) treated as cache miss, npm ci runs
Multiple worktrees N/A (no cache) each worktree has its own cache key

Test plan

  • pytest tests/hermes_cli/test_cmd_update.py -v --timeout=0 — 32 passed
  • Manual: run hermes update twice in a row, verify second run skips npm ci

Fixes #17268

@alt-glitch alt-glitch added type/perf Performance improvement or optimization P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/perf Performance improvement or optimization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Skip npm install during updates when Node dependencies haven't changed

2 participants