Skip to content

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

Merged
vincent-psarga merged 11 commits intomainfrom
cli-update
Mar 3, 2026
Merged

Add support for 'update' command to the CLI to update itself#154
vincent-psarga merged 11 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
Contributor

greptile-apps bot commented Feb 27, 2026

Greptile Summary

This PR adds a self-update capability to the CLI, allowing users to run packmind-cli update to upgrade to the latest version. The implementation intelligently detects the installation method (standalone executable vs npm package) and uses the appropriate update mechanism.

Key improvements from previous review feedback:

  • Added semver dependency to package.json for proper version comparison
  • All interfaces properly prefixed with I following TypeScript code standards
  • Version comparison now uses semver.gt() instead of string equality
  • GitHub releases explicitly sorted with semver.rcompare()

Implementation highlights:

  • Safety guards prevent updates when running via JS runtime (node/bun/deno) with helpful error messages
  • Detects local npm packages and shows appropriate update instructions
  • Atomic file replacement for executable mode prevents corruption
  • Comprehensive error handling with permission-denied suggestions
  • --check flag for CI/CD integration with proper exit codes (0=up-to-date, 1=update available)
  • File size validation prevents incomplete downloads
  • Cross-platform support for macOS, Linux, and Windows

All previously flagged issues have been addressed, and the implementation includes thorough test coverage.

Confidence Score: 5/5

  • This PR is safe to merge with no blocking issues
  • All previously identified issues have been resolved (semver dependency added, proper version comparison, interface naming conventions). The implementation includes comprehensive test coverage, robust error handling, safety guards, and follows established code standards. The feature is well-scoped with clear separation of concerns.
  • No files require special attention

Important Files Changed

Filename Overview
apps/cli/package.json Added semver dependency for proper version comparison - resolves previously flagged missing dependency issue
apps/cli/src/infra/commands/UpdateCommand.ts New command entry point that detects executable mode and delegates to handler with proper dependencies
apps/cli/src/infra/commands/updateHandler.ts Core update logic with safety guards for JS runtimes, proper semver comparison, atomic file replacement, and comprehensive error handling
apps/cli/src/infra/commands/updateHandler.spec.ts Comprehensive test coverage for all update scenarios including platform detection, version checking, JS runtime guards, and error cases
apps/cli/src/main.ts Registered new update command in CLI command registry

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Start([User runs update command]) --> CheckRuntime{Running via<br/>JS runtime?}
    CheckRuntime -->|Yes - Local npm| LocalMsg[Show: update via<br/>npm update]
    CheckRuntime -->|Yes - Global| GlobalMsg[Show: use standalone<br/>or npm install -g]
    LocalMsg --> Exit1[Exit 1]
    GlobalMsg --> Exit1
    CheckRuntime -->|No| DetectMode{Executable<br/>or npm?}
    DetectMode -->|Executable| FetchGH[Fetch latest from<br/>GitHub releases]
    DetectMode -->|npm| FetchNpm[Fetch latest from<br/>npm registry]
    FetchGH --> Validate[Filter & sort<br/>valid semver]
    FetchNpm --> Compare{Latest ><br/>Current?}
    Validate --> Compare
    Compare -->|No| UpToDate[Already up to date]
    UpToDate --> Exit0[Exit 0]
    Compare -->|Yes| CheckOnly{--check<br/>flag?}
    CheckOnly -->|Yes| ShowUpdate[Show available<br/>update]
    ShowUpdate --> Exit1
    CheckOnly -->|No| UpdateType{Update<br/>method?}
    UpdateType -->|Executable| Download[Download binary<br/>to temp file]
    Download --> AtomicReplace[Atomic rename<br/>over current]
    AtomicReplace --> SetPerms[Set executable<br/>permissions]
    SetPerms --> Success[Update successful]
    UpdateType -->|npm| RunNpm[Run npm install -g]
    RunNpm --> Success
    Success --> Exit0
Loading

Last reviewed commit: f10cfad

Copy link
Contributor

@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

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
Contributor

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
Contributor

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.

cteyton and others added 2 commits March 2, 2026 09:33
…runtime

Detects if the CLI is running via node/bun/deno and blocks the update
command to prevent accidental global npm installs or binary overwrites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the CLI is installed as a local project dependency, the update
guard now suggests `npm update @packmind/cli` instead of the generic
global install message.

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

sonarqubecloud bot commented Mar 2, 2026

@vincent-psarga vincent-psarga merged commit 673c961 into main Mar 3, 2026
17 checks passed
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.

2 participants