JFrog CLI Control Manager
Install JFCM to manage JFrog CLI versions with shim-based execution control, project pinning, version comparison, benchmarking, and usage analytics across local and CI workflows.
Overview
The JFrog CLI Control Manager (JFCM) is a developer-first execution and observability layer for the JFrog CLI (jf). It makes command-line runs predictable and auditable across laptops and continuous integration (CI) environments by controlling which binary is executed, validating behavior before rollout, and surfacing usage and performance insights.
What You Get
- Execution control: pin for each project, enforce priority through a
jfshim, run custom binaries safely - Safety before rollout: side-by-side CLI output comparison and performance benchmarking
- Observability: usage history, statistics, and replay for faster triage and support
- Version convenience: streamlined installs, aliases, and latest when you need it
Key Features
- One-command installs and switching
- Automatic project pinning via a
.jfrog-versionfile - Shell priority management with a
jfshim - Power tools for diffing, benchmarking, and usage analytics
JFCM ensures the right jf version runs every time, locally and in CI.
Why the JFrog CLI Control Manager Exists
The JFrog CLI Control Manager (JFCM) exists primarily to streamline and centralize the challenging task of managing multiple versions of the JFrog CLI (the jf binary) across different projects and environments. Its core motivation is to solve the complexity of version control that often led to difficult, manual workarounds.
Key Reasons for JFCM's Existence
1. Eliminating Manual Control Management Challenges
JFCM was created specifically to end the need for "symlink hacking or hardcoded paths" when trying to switch between different JFrog CLI versions. It removes brittle configuration and provides a smooth jf shim for command redirection to the correct, active version, ensuring the correct binary is executed every time. This also avoids "works-on-my-machine" drift between developers and CI environments.
2. Facilitating Seamless Version Switching and Installation
Inspired by managers like nvm, sdkman, and volta, JFCM streamlines obtaining and activating versions:
- Install any released version of the
jfbinary - Automatically fetch and use the latest version with
jfcm use latest - Define named aliases (for example,
prod,dev) for specific versions - Link locally built
jfbinaries for testing
3. Enabling Project-Specific Control
Different projects can rely on specific JFrog CLI versions. JFCM automatically switches the active version based on a .jfrog-version file in the current directory, ensuring the correct version is always used.
4. Supporting Advanced Development and DevOps Workflows
Beyond basic switching, JFCM enables safer upgrades and visibility into usage:
- Version testing and comparison: compare JFrog CLI command output between 2 versions with diff visualization
- Performance benchmarking: run detailed benchmarks across multiple
jfversions - Usage analytics: history and statistics on which versions and commands are used most
5. Prioritizing and Ensuring Correct Execution
JFCM manages shell integration and PATH priority so the managed jf has the highest precedence over system-installed versions (Homebrew or defaults), guaranteeing the active version is the one executed.
Why JFCM Exists
Teams ship faster when the right binary runs, behaves as expected, and is measurable:
- End manual workarounds: no symlink juggling or PATH guesswork. The
jfshim always points to the active build. - Seamless switching:
jfcm install <version>thenjfcm use <version | alias | latest> - Predictable environments: auto-activate the version in
.jfrog-versionper repository - Safer upgrades: compare outputs and benchmark before adopting a new version in CI
- Operational insight: history and statistics expose adoption, hotspots, and regressions
Execution, Safety, and Observability for the JFrog CLI
jfcm is more than a version switcher. It is a versioned, observable, and safe execution layer for the JFrog CLI. It brings the rigor of tools such as nvm, pyenv, and volta to development and operations workflows. It is tailored for artifact management and continuous integration and delivery (CI/CD).
Problem Landscape
- Inconsistent
jfversions across development, staging, and CI - Upgrade hesitancy due to fear of breaking changes
- Performance regressions that go unnoticed
- Hard-to-reproduce bugs in support and quality assurance
- Custom builds overwriting global tools
- Manual PATH and configuration errors after switching
JFCM Solution
- Version isolation for each project, alias, or workflow
- Compare: command-level output diffs across versions
- Benchmark: performance checks with statistics and export
- History: observability of versions and commands over time
- Link: test custom or local binaries without touching global
jf - Hooks: pre-execution and post-execution hooks for standardization
Outcome: predictable pipelines, safer upgrades, faster triage, confident feature adoption.
Value by Role
The following table summarizes how JFCM helps different roles.
| Role | What JFCM Enables |
|---|---|
| Developers | Project-pinned versions, quick alias switching, and safe testing of local builds. |
| DevOps and Platform | Version-safe CI/CD, drift-free runners, and data-driven upgrades with compare and benchmark. |
| Quality Assurance and Test | Systematic cross-version validation and regression detection before rollout. |
| Support and SRE | Reproduce issues with history, diff behavior with compare, and cut mean time to resolution. |
| Security and compliance | Enforce allowed versions with jfcm block, and audit usage with history --stats. |
| Enterprise Admins | Org-wide standardization, visibility, and controlled rollouts. |
| Research and Development and Plugin Developers | Sandbox experimental builds with link, and trace behavior over runs. |
JFCM Features in Full Detail
1. Version Management
JFCM provides seamless handling and organization of JFrog CLI versions, so you can install, switch, and maintain different binaries:
- Installation: Installs any released
jfbinary version from JFrog's public release server (for example,jfcm install <version>) - Activation and switching (use): Activates a specified version or alias (for example,
jfcm use <version or alias>). Usejfcm use latestto fetch and activate the most recent version automatically - Project-Specific Defaults: Automatic switching based on a
.jfrog-versionfile in the current directory ensures consistency - Aliasing: Define custom aliases for specific versions (for example,
prod,dev) - Local Linking: Link a locally built
jfbinary for use via JFCM - Removal and Listing:
jfcm remove <version>,jfcm clear, andjfcm list
2. Shell Integration and Priority Management
JFCM automatically configures your shell to ensure that managed jf binaries have the highest priority over system-installed versions. This is achieved by:
- Creating a shim (at
~/.jfcm/shim/jf) that redirects commands to the currently active version - Updating the PATH environment variable to prioritize the JFCM shim directory
- Adding a shell function for enhanced priority handling (similar to the
nvmapproach)
3. Advanced Comparison and Benchmarking Features
The following tools benefit development and DevOps teams:
- Parallel Command Comparison (
jfcm compare cli): Compare JFrog CLI command output between 2 versions simultaneously, with Git-like diff visualization (side-by-side or unified), colored output, and comparison of execution timing, exit codes, and error output - Changelog Comparison (
jfcm compare changelog): Compare release notes and changelogs between 2 versions - Performance Benchmarking (
jfcm benchmark): Run detailed performance benchmarks across multiple JFrog CLI versions, configurable iterations, statistics (minimum, maximum, average), and exports (table, JSON, CSV)
4. Usage Analytics and Health Checks
- Usage History (
jfcm history): Tracks version usage patterns, including command timing, usage trends, most-used versions and commands. History replay allows re-executing previous commands using!\{id\} - Health Check (
jfcm health-check): Comprehensive check covering environment, PATH, network connectivity, performance checks, and security checks. Includes--fixto address common issues
Procedures
The following procedures walk you through installing, managing, and troubleshooting JFCM:
- Install JFCM
- Manage and upgrade JFrog CLI versions
- Troubleshoot PATH priority issues
- Upgrade or uninstall JFCM
Installation
Install JFCM on macOS with Homebrew or by building from source. If you have not installed the JFrog CLI yet, see Download and Install the JFrog CLI first. After installation, verify that the shim directory is first on your PATH.
This section covers the following procedures:
Install JFCM on macOS with Homebrew
To install JFCM on macOS with Homebrew:
-
Tap the JFCM Homebrew repository:
brew tap jfrog/jfrog-cli-manager -
Install JFCM:
brew install jfcmIf the formula is not found, search for it or install directly from the repository URL:
brew search jfcm brew install https://raw.githubusercontent.com/jfrog/homebrew-jfrog-cli-manager/main/Formula/jfcm.rb
Build JFCM from Source on macOS and Linux
Prerequisite: A Go toolchain is required to build from source.
To build and install JFCM from source:
-
Clone the repository and change into the project directory:
git clone https://github.com/jfrog/jfrog-cli-manager.git cd jfrog-cli-manager -
Build and install JFCM:
make build make installThe
make installcommand copies thejfcmexecutable to~/.jfcm/shim. You can also runmake bootstrapto add~/.jfcm/shimto your shell'sPATH.
Post-Installation and Verification
After installation, the shim directory ($HOME/.jfcm/shim) must be prioritized at the beginning of your $PATH so JFCM-managed jf versions take precedence.
To verify JFCM installation:
-
Confirm
PATHpriority:echo $PATHThe output should start with
~/.jfcm/shim. -
Confirm JFCM responds:
jfcm --help jfcm list
For upgrade or complete removal of JFCM, see Upgrade and Uninstall at the end of this page.
Managing and Upgrading JFrog CLI Versions
Once JFCM is installed, use the following procedures to install, activate, and pin JFrog CLI versions. For authentication after switching versions, see Authenticating via the CLI.
Installing Specific Versions
To install a specific jf binary:
-
Run
jfcm installwith the target version:jfcm install <VERSION>Where:
<VERSION>: The JFrog CLI release version to install (for example,2.74.0)
For example:
jfcm install 2.74.0
Switching to and Activating a Version
To activate a JFrog CLI version:
-
Run
jfcm usewith a version, alias, orlatest:jfcm use <VERSION_OR_ALIAS> jfcm use latestWhere:
<VERSION_OR_ALIAS>: An installed version number or a defined alias (for example,2.74.0orprod)latest: Fetches or installs the newest release, then activates it
Handling Project-Specific Versions
To pin a JFrog CLI version for a repository:
-
Create a
.jfrog-versionfile in the repository root:echo "2.74.0" > .jfrog-versionYou can also store a constraint (for example,
>=2.74.0,>2.74.0,<=2.80.0,<2.80.0, or=2.74.0). JFCM selects the highest installed version that satisfies the constraint.For example:
echo ">=2.74.0" > .jfrog-version -
Activate the pinned version:
jfcm useJFCM automatically uses the version or constraint in
.jfrog-version.
Health Check and Troubleshooting
To verify JFCM setup and resolve common issues:
-
Run the health check with verbose output and auto-fix:
jfcm health-check --verbose --fixThis verifies PATH configuration and related settings. Add
--verbosewhen you need more detail for troubleshooting.
Core Commands
The following table lists commands that handle installation, removal, switching, aliasing, and version policy for JFrog CLI versions.
| Command | Syntax and example | What it does and how it works | When to use it |
|---|---|---|---|
| install | jfcm install <version>(for example, jfcm install 2.74.0) | Installs the specified version of the JFrog CLI (jf). It downloads the binary from JFrog's public release server. | When you need a specific version of jf that isn't installed. |
| use | jfcm use <version or alias>(for example, jfcm use 2.74.0, jfcm use latest, jfcm use prod) | Activates the given version or alias, making it the active jf binary. Sets up PATH priority so JFCM-managed jf takes precedence over system versions. | Switch versions. jfcm use latest auto-fetches and activates the newest version (downloading if needed). If you pass no argument, it uses the version in .jfrog-version. |
| list | jfcm list | Shows all installed versions of jf and indicates which one is active. | Review managed versions on your system. |
| remove | jfcm remove <version>(for example, jfcm remove 2.72.1) | Removes a specific installed jf version. | Clean up old or unused versions. |
| clear | jfcm clear | Removes all installed versions of jf. | Complete cleanup of all JFCM-managed binaries. |
| alias | jfcm alias set <name> <version>(for example, jfcm alias set dev 2.74.0)Optional: --description "purpose" | Defines a named alias for a specific version. Use jfcm alias list, jfcm alias get, or jfcm alias remove to manage aliases. | Friendly names (for example, prod, dev) for jfcm use. |
| link | jfcm link --from <path> --name <n>(for example, jfcm link --from /Users/Jfrog/go/bin/jf --name local-dev) | Links a locally built jf so you can use and manage it through JFCM. Then run jfcm use <n> to activate. | Developing or testing local or unreleased builds. |
| block | jfcm block <version> | Blocks a specific version from activation. | Security and compliance policies that forbid certain builds. |
| unblock | jfcm unblock <version> | Removes a version block. | When a previously blocked version is approved again. |
| list-blocked | jfcm list-blocked (alias lb) | Lists blocked versions. | Auditing which versions cannot run. |
| health-check | jfcm health-check [options](for example, --fix, --verbose, --performance, --security) | Performs a comprehensive health check: install status, shim setup, PATH, network connectivity, binary execution, and basic performance and security checks. --fix auto-resolves common issues. | Initial setup verification and troubleshooting PATH or priority issues. |
Advanced Features Commands
JFCM uses multiple versions simultaneously for comparison, benchmarking, and analytics.
Compare Behavior Between 2 Versions
Run the same jf command twice and compare the outputs.
jfcm compare cli <v1> <v2> -- <jf command>
# Examples:
jfcm compare cli 2.74.0 2.73.0 -- --version
jfcm compare cli prod dev -- rt pingFeatures:
- Git-like diff visualization (side-by-side or unified)
- Colored output, and compares execution timing, exit codes, and stderr
- When to use it: version testing before upgrade, configuration diffs (for example,
config show), and feature verification
Changelog Comparison
jfcm compare changelog <v1> <v2>
# Example:
jfcm compare changelog v2.75.1 v2.76.0Compares release notes and changelogs between 2 JFrog CLI versions.
Compare the Same Command Across Servers
Run the same JFrog CLI command against 2 different server configurations and diff the results. Use this when you need to compare behavior across environments (for example, production and staging).
jfcm compare rt <server1> <server2> -- <jf-command> [arguments...]Performance Benchmarking
Run performance tests across multiple versions:
jfcm benchmark <versions> -- <command> [options]
# Examples:
jfcm benchmark 2.74.0,2.73.0,2.72.0 -- rt search "*.jar" --format csv
jfcm benchmark prod,dev -- rt upload test.txt my-repository/ --iterations 5 --detailedFeatures:
- Parallel execution and configurable iterations
- Statistics (minimum, maximum, average) and performance ranking
- Export results as table, JSON, CSV
Usage Analytics with jfcm history
Track and analyze historical usage of jf versions.
jfcm history # recent usage
jfcm history --stats # aggregate statistics
jfcm history --version 2.74.0
jfcm history '!5' # replay the command with id 5Features:
-
Tracks usage patterns (command, version, timestamps), limited to 1000 entries
-
Detailed statistics, filter by version, and history replay via
!\{id\}. You can narrow output with flags such as--command <pattern>,--failures-only,--show-output,--limit <n>,--format json, or--clear. -
Stored at
~/.jfcm/history.json
Shell Integration and Priority Management
The core goal of JFCM's shell integration is to ensure that when you run jf, the JFCM-managed version executes, not a system-installed binary (like Homebrew or OS defaults).
When you run jfcm use <version>, it:
- Creates a shim at
~/.jfcm/shim/jfthat redirects to the active version - Updates the PATH to prioritize the JFCM shim directory
- Adds a shell function for enhanced priority handling (similar to the
nvmapproach)
Profile Snippet for Auto-Priority
# jfcm PATH configuration - ensures jfcm-managed jf takes highest priority
export PATH="$HOME/.jfcm/shim:$PATH"
# jfcm shell function for enhanced priority (similar to nvm approach)
jf() {
# Check if jfcm shim exists and is executable
if [ -x "$HOME/.jfcm/shim/jf" ]; then
# Execute jfcm-managed jf with highest priority
"$HOME/.jfcm/shim/jf" "$@"
else
# Fallback to system jf if jfcm shim not available
command jf "$@"
fi
}Debug Mode
export jfcm_DEBUG=1
# Shows which version is being executed
jf --versionSet jfcm_NO_HISTORY=1 to disable history recording. This helps in CI pipelines or when you run sensitive commands you do not want stored.
Troubleshooting PATH Issues
If jf still resolves to a system binary instead of the JFCM-managed version, follow these steps.
To troubleshoot PATH priority issues:
-
Run the health check and apply fixes:
jfcm health-check --fix -
Confirm which
jfbinary runs:which jfThe output should show
~/.jfcm/shim/jf. -
Verify
PATHorder:echo $PATH~/.jfcm/shimshould appear before/usr/local/binor/opt/homebrew/bin. -
Re-activate the version and reload your shell profile:
jfcm use <VERSION> source ~/.zshrcWhere:
<VERSION>: The JFrog CLI version or alias to activate
-
If needed, add the shim directory to your shell profile manually:
export PATH="$HOME/.jfcm/shim:$PATH" -
Check for shell function conflicts:
type jfThe output should show the JFCM shell function, not a system binary.
Advanced Examples
Comparing Configuration Changes
# Compare configuration differences between versions
jfcm compare cli 2.74.0 2.73.0 -- config show --format json
# Check if a specific feature works across versions
jfcm compare cli old new -- rt search "libs-release-local/*.jar" --limit 5
# Compare release notes and changelogs
jfcm compare changelog v2.75.1 v2.76.0Performance Analysis
# Benchmark search performance across versions
jfcm benchmark 2.74.0,2.73.0,2.72.0 -- rt search "*" --limit 100 --iterations 3
# Test upload performance
jfcm benchmark prod,dev -- rt upload test.txt my-repository/ --iterations 5 --detailedUsage Analytics
# See your most used JFrog CLI commands
jfcm history --stats
# Track version adoption over time
jfcm history --version 2.74.0Automation and CI
# Export benchmark results for CI analysis
jfcm benchmark $OLD_VERSION,$NEW_VERSION -- rt ping --format json > performance.json
# Compare outputs in automated testing
jfcm compare cli baseline canary --unified --no-color -- rt search "*.jar"
# Always use the latest version in CI pipelines
jfcm use latest
jf --versionAdvanced Configuration in JFCM
JFCM manages configuration settings related to usage tracking, performance, and installation health. You can fine-tune the tool's behavior and analyze its operations.
History Management
- History is automatically tracked in
~/.jfcm/history.json - The history log is limited to ~1000 entries to prevent unlimited growth
- Tracked data includes command execution timing and associated metadata
- Usage history provides insights into most used versions and commands
- Options: filter by version (
--version 2.74.0), show detailed statistics (--stats), or replay using!\{id\}(for example,jfcm history '!5')
Health Check Features
Feature Category → Detailed Checks:
- Installation Status: verifies JFCM directories, shim setup, PATH configuration
- Priority Verification: ensures the managed
jfhas priority over system-installed versions - System Environment: checks OS compatibility, architecture, shell detection
- Binary Execution: tests running both
jfcmandjf - Network Connectivity: confirms reachability to GitHub API and JFrog releases infrastructure
- Performance and security: includes performance checks and basic security checks (file permissions, suspicious file detection)
- Advanced output and fixes:
--fixauto-resolves common issues, and supports JSON output for CI/CD
Performance Optimization
- Commands are designed to run in parallel when possible to speed up comparisons and benchmarks
- Supports configurable timeouts for long-running operations
- Efficient diff algorithms are used when comparing large command results
Debugging for CI Pipelines
- Debug Mode:
jfcm_DEBUG=1reveals detailed shim execution information (which version is executed) - Automation: you can export benchmark results as JSON or CSV. Comparison output supports
--unifiedand--no-colorfor reliable, deterministic diffs in CI.
Note
The JFrog CLI Control Manager (JFCM) addresses the challenges of managing multiple JFrog CLI (
jf) versions across projects and environments. It streamlines management, automatic installation, version switching, and analytics, drawing inspiration fromnvm,sdkman, andvolta.
CI/CD Quick Tips
Always Latest
jfcm use latest
jf --versionBaseline vs Canary
jfcm compare cli baseline canary --unified --no-color -- rt search "*.jar"Export Performance Data
Use --format json or --format csv for dashboards and regression alarms.
Quick Troubleshooting
Use the following table for quick fixes to common problems.
| Issue | Solution |
|---|---|
jf resolves to system binary | Ensure ~/.jfcm/shim is first on PATH, and run jfcm health-check --fix |
| Network or permissions issues | Rerun with --verbose, and verify proxy and file permissions |
| Local build not used | Run jfcm link --from /path/to/jf --name local-dev, then jfcm use local-dev |
Upgrade and Uninstall
Use these procedures to upgrade or remove JFCM and all managed JFrog CLI versions.
To upgrade JFCM:
brew upgrade jfcmTo uninstall JFCM completely:
-
If installed via Homebrew, run:
brew uninstall jfcm -
Remove the JFCM installation directory:
rm -rf ~/.jfcmThis removes all installed
jfversions, the shim at~/.jfcm/shim/jf, the history file at~/.jfcm/history.json, and configuration and aliases.
Frequently Asked Questions
This section provides answers to frequently asked questions about JFCM.
FAQs
Q: What is JFCM?
A: JFCM is a version manager and execution layer for the JFrog CLI (jf) that installs, activates, and prioritizes specific versions through a shim. For background, see Why the JFrog CLI Control Manager Exists.
Q: How do I install JFCM?
A: On macOS, run brew tap jfrog/jfrog-cli-manager and brew install jfcm, or build from source with make build and make install. See Installation for the full procedure.
Q: How do I install and switch JFrog CLI versions with JFCM?
A: Run jfcm install <version> to add a release, then jfcm use <version or alias> or jfcm use latest to activate it. See Managing and Upgrading JFrog CLI Versions.
Q: What is the difference between jfcm use and a system-installed jf?
jfcm use and a system-installed jf?A: jfcm use activates a managed binary through the shim at ~/.jfcm/shim/jf, which takes priority over Homebrew or OS defaults on PATH. See Shell Integration and Priority Management.
Q: What happens if jf resolves to the system binary instead of JFCM?
jf resolves to the system binary instead of JFCM?A: Ensure ~/.jfcm/shim is first on PATH, run jfcm health-check --fix, and re-run jfcm use <version>. See Troubleshooting PATH Issues.
Q: What do I need before building JFCM from source?
A: You need a Go toolchain and network access to clone https://github.com/jfrog/jfrog-cli-manager.git. See Build JFCM from Source on macOS and Linux.
Q: Can I pin a JFrog CLI version per project?
A: Yes. Add a .jfrog-version file to the repository (for example, 2.74.0 or >=2.74.0), then run jfcm use with no arguments. See Handling Project-Specific Versions.
Q: How do I compare JFrog CLI versions before upgrading?
A: Run jfcm compare cli <V1> <V2> -- <JF_COMMAND> for output diffs and jfcm compare changelog <V1> <V2> for release notes. See Compare Behavior Between 2 Versions.
