Skip to content

fix(cli): scope upgrade command to detected install mode#896

Open
rohitg00 wants to merge 4 commits into
mainfrom
fix/upgrade-command
Open

fix(cli): scope upgrade command to detected install mode#896
rohitg00 wants to merge 4 commits into
mainfrom
fix/upgrade-command

Conversation

@rohitg00

@rohitg00 rohitg00 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

agentmemory upgrade ran npm install in whatever cwd had a package.json, which mutated unrelated user projects and added iii-sdk as a dependency there, while never upgrading agentmemory itself for npx or global users.

New src/cli/install-mode.ts classifies the invocation as local-dev (cwd package.json names @agentmemory/agentmemory), npx, or global, and the existing npx heuristic now delegates to the shared helper. runUpgrade keeps the dependency refresh and iii-sdk pin only in local-dev mode, prints upgrade instructions in npx mode without mutating anything, and runs npm install -g @agentmemory/agentmemory@latest in global mode. The closing note reminds users to re-run agentmemory connect claude-code --with-hooks so hook entries pointing at versioned absolute plugin paths get refreshed after the upgrade.

Tested by test/install-mode.test.ts with the full mode matrix.

Summary by CodeRabbit

  • New Features
    • Centralized CLI install-mode detection (local-dev, npx, global) and improved upgrade guidance, including a recommended agentmemory connect claude-code --with-hooks step.
  • Bug Fixes
    • Clearer handling and messaging for npx invocations (prints upgrade note instead of in-place upgrade) and warnings/manual-upgrade guidance when npm tooling is missing.
  • Tests
    • Added tests for install-mode detection and package manifest reading.

agentmemory upgrade ran npm install in whatever cwd had a package.json,
which mutated unrelated user projects and added iii-sdk as a dependency
there, while never upgrading agentmemory itself for npx or global users.

Add src/cli/install-mode.ts with a pure detectInstallMode helper that
classifies the invocation as local-dev (cwd package.json names
@agentmemory/agentmemory), npx, or global, and extract the existing npx
heuristic into isNpxInvocation so the CLI delegates to one shared
implementation.

runUpgrade now keeps the dependency refresh and iii-sdk pin only in
local-dev mode, prints upgrade instructions in npx mode without mutating
anything, and runs npm install -g @agentmemory/agentmemory@latest in
global mode. The engine confirm, pinned iii installer, and pinned Docker
pull are unchanged. The closing note now reminds users to re-run
agentmemory connect claude-code --with-hooks so hook entries pointing at
absolute plugin paths get refreshed after the upgrade.

Covered by test/install-mode.test.ts with the full mode matrix.
@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agentmemory Ready Ready Preview, Comment Jun 10, 2026 11:07pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 06e75f43-b406-4726-91ed-e31086e7b5b1

📥 Commits

Reviewing files that changed from the base of the PR and between 857b649 and 4fa0ac2.

📒 Files selected for processing (2)
  • src/cli/install-mode.ts
  • test/install-mode.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/install-mode.test.ts
  • src/cli/install-mode.ts

📝 Walkthrough

Walkthrough

Adds an install-mode detection module (local-dev, npx, global), integrates it into CLI npx detection and the upgrade command to choose mode-appropriate messaging/behavior, and adds Vitest coverage for the new utilities.

Changes

Install-mode detection and upgrade path selection

Layer / File(s) Summary
Install-mode detection module and signal types
src/cli/install-mode.ts
Exports OWN_PACKAGE_NAME, InstallMode ("local-dev" | "npx" | "global"), NpxSignals/InstallModeInputs, and functions isNpxInvocation, detectInstallMode, readCwdPackageName to classify invocation context and read cwd package name.
Test coverage for install-mode detection
test/install-mode.test.ts
Vitest suite validating isNpxInvocation heuristics (lifecycle event, argv1 _npx, npm user-agent), detectInstallMode precedence (local-dev > npx > global), and readCwdPackageName with valid, missing, malformed, and array-shaped manifests.
NPX invocation detection in CLI main entry
src/cli.ts (lines 44–48, 582–586)
Imports isNpxInvocation, detectInstallMode, readCwdPackageName and replaces inline NPX heuristic with isNpxInvocation(process.argv[1], process.env.npm_lifecycle_event, process.env.npm_config_user_agent).
Upgrade command refactoring with install-mode branching
src/cli.ts (lines 2272–2369)
runUpgrade now uses detectInstallMode (cwd package name + npm env signals) to branch: local-dev (in-place upgrade path), npx (print CLI upgrade instructions), global (attempt upgrade or warn when npm missing); updates recommended next steps to include agentmemory connect claude-code --with-hooks.

Sequence Diagram(s)

No sequence diagrams generated.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • rohitg00/agentmemory#581: The upgrade flow now recommends running agentmemory connect claude-code --with-hooks, which directly depends on the newly added --with-hooks implementation for installing and updating Claude Code hook paths.

Poem

🐰 I sniffed the argv, the npm tales,

local, npx, or global trails;
Small hops of code to make things clear,
Upgrade notes now fit the sphere;
With hooks in tow, the CLI cheers!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: refactoring the upgrade command to detect and respond appropriately to different CLI installation modes (local-dev, npx, global).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/upgrade-command

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

The skills reference generator scans source for AGENTMEMORY_ prefixed
tokens to build the recognized env var list, and the exported package
name constant matched the pattern, documenting a config variable that
does not exist.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/cli.ts (2)

2362-2370: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Make the follow-up commands mode-aware too.

The npx branch on Line 2315 says there is no installed CLI, but this final note still tells that same user to run bare agentmemory status and agentmemory connect .... In mode === "npx", those next steps can fail immediately; build the displayed command prefix from mode here as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli.ts` around lines 2362 - 2370, The follow-up note shown via p.note
currently prints bare commands regardless of CLI mode; make it mode-aware by
constructing a command prefix based on the existing mode variable (e.g., use
"npx agentmemory" when mode === 'npx' versus "agentmemory" for installed mode)
and use that prefix for the displayed commands (the entries passed into p.note).
Update the logic that builds the array for p.note to compute and insert this
prefix before "status" and "connect claude-code --with-hooks" so the printed
next steps match the actual invocation method.

2292-2314: ⚠️ Potential issue | 🟠 Major

Abort instead of switching from a detected pnpm-lock.yaml checkout to npm
In src/cli.ts (local-dev branch), pnpm-lock.yaml only triggers the pnpm install path when pnpmBin is present; if pnpm is missing but npm exists, the code falls through to the npm install/iii-sdk pin path. That runs the wrong package-manager tooling against a pnpm-managed repo and can dirty node_modules and lockfiles.

Suggested fix
   if (mode === "local-dev") {
     const hasPnpmLock = existsSync(join(cwd, "pnpm-lock.yaml"));
-    if (pnpmBin && hasPnpmLock) {
+    if (hasPnpmLock) {
+      if (!pnpmBin) {
+        p.log.error("pnpm-lock.yaml detected but `pnpm` is not on PATH.");
+        process.exit(1);
+      }
       const installOk = runCommand(pnpmBin, ["install"], {
         label: "Refreshing dependencies (pnpm install)",
       });
       requireSuccess(installOk, "pnpm install");
       runCommand(pnpmBin, ["up", "iii-sdk@0.11.2"], {
         label: "Pinning iii-sdk@0.11.2",
         optional: true,
       });
     } else if (npmBin) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli.ts` around lines 2292 - 2314, The local-dev block currently falls
back to npm when a pnpm-managed repo is detected (hasPnpmLock) but pnpmBin is
missing; change the logic in the mode === "local-dev" branch so that if
hasPnpmLock is true and pnpmBin is falsy you abort instead of using npm (do not
proceed to the npmBin path). Specifically, update the conditional around
hasPnpmLock/pnpmBin and npmBin (the code that calls runCommand and
requireSuccess) to: when hasPnpmLock && !pnpmBin, log a clear error via
p.log.error (or throw/exit similarly) and stop execution; only allow npm paths
when no pnpm-lock is present. Adjust handling around pnpmBin, hasPnpmLock,
npmBin, runCommand and requireSuccess accordingly.
🧹 Nitpick comments (1)
src/cli/install-mode.ts (1)

18-24: pnpm-as-npx-like is intentional—don’t tighten the UA match without changing tests

  • isNpxInvocation() treats pnpm user agents that embed " npm/" as npx-like (ua.includes(" npm/")), and test/install-mode.test.ts explicitly asserts "pnpm/9.0.0 npm/? node/v22.0.0" returns true.
  • This result is used in isInvokedViaNpx() to drive the first-run global-install prompt (maybeOfferGlobalInstall()), so widening the heuristic is likely deliberate.
  • If anything, rename for clarity (e.g., “isNpxLikeInvocation”) since the logic is broader than “npx” naming suggests.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/install-mode.ts` around lines 18 - 24, The function isNpxInvocation
has broader heuristics (accepts pnpm user-agents containing " npm/") so rename
it to isNpxLikeInvocation for clarity and update all call sites and tests
accordingly: change the exported function name isNpxInvocation to
isNpxLikeInvocation, update any imports/usages such as isInvokedViaNpx and
maybeOfferGlobalInstall to call the new name, and update test expectations in
test/install-mode.test.ts (and any other tests) to reference the renamed
function so behavior remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cli.ts`:
- Around line 2272-2277: The install-mode detection misclassifies normal npm
runs as "npx" because we pass process.env["npm_config_user_agent"] into
detectInstallMode; update the callsite or the detector so npx is identified only
via explicit markers: remove npmUserAgent from the argument list (i.e., stop
passing process.env["npm_config_user_agent"] to detectInstallMode) or change
detectInstallMode to only treat npx when npm_lifecycle_event === "npx", argv1
contains "_npx", or the user-agent explicitly indicates npx (not just any
"npm/"); reference detectInstallMode, readCwdPackageName, argv1, and
process.env["npm_lifecycle_event"] when making the change.

---

Outside diff comments:
In `@src/cli.ts`:
- Around line 2362-2370: The follow-up note shown via p.note currently prints
bare commands regardless of CLI mode; make it mode-aware by constructing a
command prefix based on the existing mode variable (e.g., use "npx agentmemory"
when mode === 'npx' versus "agentmemory" for installed mode) and use that prefix
for the displayed commands (the entries passed into p.note). Update the logic
that builds the array for p.note to compute and insert this prefix before
"status" and "connect claude-code --with-hooks" so the printed next steps match
the actual invocation method.
- Around line 2292-2314: The local-dev block currently falls back to npm when a
pnpm-managed repo is detected (hasPnpmLock) but pnpmBin is missing; change the
logic in the mode === "local-dev" branch so that if hasPnpmLock is true and
pnpmBin is falsy you abort instead of using npm (do not proceed to the npmBin
path). Specifically, update the conditional around hasPnpmLock/pnpmBin and
npmBin (the code that calls runCommand and requireSuccess) to: when hasPnpmLock
&& !pnpmBin, log a clear error via p.log.error (or throw/exit similarly) and
stop execution; only allow npm paths when no pnpm-lock is present. Adjust
handling around pnpmBin, hasPnpmLock, npmBin, runCommand and requireSuccess
accordingly.

---

Nitpick comments:
In `@src/cli/install-mode.ts`:
- Around line 18-24: The function isNpxInvocation has broader heuristics
(accepts pnpm user-agents containing " npm/") so rename it to
isNpxLikeInvocation for clarity and update all call sites and tests accordingly:
change the exported function name isNpxInvocation to isNpxLikeInvocation, update
any imports/usages such as isInvokedViaNpx and maybeOfferGlobalInstall to call
the new name, and update test expectations in test/install-mode.test.ts (and any
other tests) to reference the renamed function so behavior remains unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 63844e97-f778-42d0-9792-581df3c55f24

📥 Commits

Reviewing files that changed from the base of the PR and between 25e7701 and 92338bd.

📒 Files selected for processing (3)
  • src/cli.ts
  • src/cli/install-mode.ts
  • test/install-mode.test.ts

Comment thread src/cli.ts
npm_config_user_agent starts with npm/ for every npm-mediated run
including npm run scripts and lifecycle hooks, so matching it
misclassified globally installed users invoking upgrade through an npm
script and printed instructions instead of upgrading. npx detection now
requires the npx lifecycle event, the _npx cache directory in argv[1],
or a user agent that names npx itself.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant