Skip to content

Add support for 'update' command to the CLI to update itself#154

Open
cteyton wants to merge 9 commits intomainfrom
cli-update
Open

Add support for 'update' command to the CLI to update itself#154
cteyton wants to merge 9 commits intomainfrom
cli-update

Conversation

@cteyton
Copy link
Contributor

@cteyton cteyton commented Feb 27, 2026

Explanation

Let users easily update the CLI to its latest version.

Type of Change

  • Bug fix
  • New feature
  • Improvement/Enhancement
  • Refactoring
  • Documentation
  • Breaking change

Affected Components

  • Domain packages affected: CLI

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing completed
  • Test coverage maintained or improved

TODO List

  • CHANGELOG Updated
  • Documentation Updated
@greptile-apps
Copy link

greptile-apps bot commented Feb 27, 2026

Greptile Summary

This PR adds a self-update command to the CLI that allows users to easily update to the latest version. The implementation properly handles both npm package and standalone executable modes.

Key improvements from previous feedback:

  • ✅ Now uses semver.gt() for proper version comparison instead of string equality
  • ✅ GitHub releases are explicitly sorted by semver to ensure correct latest version detection
  • ✅ All interfaces correctly prefixed with I per TypeScript code standards
  • semver dependency added to package.json

Implementation highlights:

  • --check flag exits with code 1 when update is available, code 0 when up to date (enables scripting)
  • Proper error handling with specific messaging for permission errors
  • Atomic file replacement for executable updates with temp file cleanup on failure
  • File size validation after download to detect incomplete downloads
  • Comprehensive test coverage including edge cases

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk
  • Score reflects well-tested implementation that addresses all previous feedback, proper error handling, and comprehensive test coverage. Minor consideration: Windows executable replacement may fail for running executables (documented limitation)
  • No files require special attention - all previous issues have been addressed

Important Files Changed

Filename Overview
apps/cli/src/infra/commands/UpdateCommand.ts New command entry point - clean implementation with proper dependency injection
apps/cli/src/infra/commands/updateHandler.ts Core update logic with proper semver comparison, error handling, and both npm/executable update paths. Interfaces correctly prefixed with I per standards
apps/cli/src/infra/commands/updateHandler.spec.ts Comprehensive test coverage for all update scenarios including edge cases

Last reviewed commit: 0be3345

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 7 comments

Edit Code Review Agent Settings | Greptile


function updateViaNpm(version: string): void {
logInfoConsole(`Updating via npm to version ${version}...`);
execSync(`npm install -g ${NPM_PACKAGE}@${version}`, {
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if I have @packmind/cli in my local JS dependencies (in my package.json)

My guess is that the general packmind-cli will be updated but if I run it inside my project I'll still have the old version.

Copy link
Contributor Author

@cteyton cteyton Feb 27, 2026

Choose a reason for hiding this comment

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

I don't think this should be covered by our update command, since it would imply directly updating the package.json file.
I think it'd more the jobs of some tools like dependabot, don't you think?

cteyton and others added 3 commits February 27, 2026 17:11
- Replace string equality with semver.gt() for correct handling
  of versions like 0.9.0 vs 0.10.0
- Fix test names to follow verb-first naming convention
- Add test for current version newer than latest

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…order

Explicitly sort CLI releases using semver.rcompare to ensure the latest
version is selected regardless of GitHub API response ordering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cteyton and others added 2 commits February 27, 2026 17:22
- Add checkOnly boolean flag to IUpdateHandlerDependencies
- Skip download/npm install when --check-update is passed
- Add tests for check-only mode (update available and up to date)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cteyton
Copy link
Contributor Author

cteyton commented Feb 28, 2026

@greptile thoughts on the "--check-update" flag?

@greptile-apps
Copy link

greptile-apps bot commented Feb 28, 2026

Looking at the implementation, the --check-update flag is solid and useful. Here are my thoughts:

What works well:

  • Non-destructive checking before committing to an update
  • Good for automation/CI scripts that want to detect outdated installations
  • Clean exit without side effects when flag is present

Suggestions:

  1. Consider shorter flag name: --check is more conventional than --check-update. Compare:

    • packmind-cli update --check
    • vs packmind-cli update --check-update (redundant?)
  2. Add exit codes: When running in check-only mode, consider:

    • Exit 0: Already up-to-date
    • Exit 1: Update available
    • This makes it easy to use in scripts: if packmind-cli update --check; then ...
  3. Consider alternative: separate subcommand: Some CLIs use update check vs update install, but for this use case the flag approach is fine.

The implementation in updateHandler.ts handles it cleanly:

if (deps.checkOnly) {
  return;  // Exit after logging version comparison
}

Overall, it's a good addition. The only change I'd strongly recommend is shortening the flag to just --check.

cteyton and others added 2 commits February 28, 2026 08:09
- Rename flag from --check-update to --check for brevity
- Exit with code 1 when update is available in check-only mode
- Exit with code 0 when already up to date (enables scripting)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cteyton
Copy link
Contributor Author

cteyton commented Feb 28, 2026

Looking at the implementation, the --check-update flag is solid and useful. Here are my thoughts:

What works well:

  • Non-destructive checking before committing to an update
  • Good for automation/CI scripts that want to detect outdated installations
  • Clean exit without side effects when flag is present

Suggestions:

  1. Consider shorter flag name: --check is more conventional than --check-update. Compare:

    • packmind-cli update --check
    • vs packmind-cli update --check-update (redundant?)
  2. Add exit codes: When running in check-only mode, consider:

    • Exit 0: Already up-to-date
    • Exit 1: Update available
    • This makes it easy to use in scripts: if packmind-cli update --check; then ...
  3. Consider alternative: separate subcommand: Some CLIs use update check vs update install, but for this use case the flag approach is fine.

The implementation in updateHandler.ts handles it cleanly:

if (deps.checkOnly) {
  return;  // Exit after logging version comparison
}

Overall, it's a good addition. The only change I'd strongly recommend is shortening the flag to just --check.

@greptile can you report on the updated version?

@greptile-apps
Copy link

greptile-apps bot commented Feb 28, 2026

Great news! Both of your key suggestions have been implemented:

✅ Changes Made

1. Flag shortened to --check

check: flag({
  long: 'check',
  description: 'Only check if a newer version is available without performing the update',
}),

Usage is now: packmind-cli update --check

2. Exit codes implemented
From the updateHandler implementation:

  • Exit 0: When already up-to-date (implicit return)
  • Exit 1: When update is available (explicit process.exit(1))

This makes it script-friendly:

if packmind-cli update --check; then
  echo "Up to date!"
else
  echo "Update available"
fi

The implementation is clean and follows the conventional pattern you recommended. The handler checks the version, logs the result, and exits appropriately in check-only mode before attempting any actual update.

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

Labels

None yet

2 participants