Native Mode

Enable Native Mode to run build tools with your own configuration and JFrog CLI build-info.

JFrog CLI provides two execution modes for package managers: Wrapped Mode (default) and Native Mode (opt-in). This page explains the difference, which tools support Native Mode, and how to configure each one.

This topic covers the following tasks:

📘

Package Alias is not Native Mode

Package Alias (Ghost Frog) lets you run native commands such as mvn install or npm install without the jf prefix while JFrog CLI still intercepts and routes them. Native Mode still requires jf mvn or jf npm — it only changes how the underlying tool executes inside JFrog CLI. Use Package Alias when you cannot change existing scripts. Use Native Mode when you want full control of tool configuration files.


Prerequisites

Before using any build-tool command, ensure the following are in place:

RequirementDetails
JFrog CLI configuredRun jf config add at least once. Verify with jf config show.
Tool installedInstall the package manager you intend to use (Maven, Gradle, npm, Poetry, Docker).
Tool-specific runtimeMaven and Gradle require Java in PATH. Verify with java -version.
Docker daemon runningDocker Native Mode requires the Docker daemon to be active. Verify with docker info.
Artifactory accessFor Native Mode: a repository must exist and credentials must be configured via Artifactory Set Me Up. For Wrapped Mode: run jf <tool>-config first.
👍

Tip

If you have multiple JFrog servers configured, identify your default server with jf config show. All jf rt build-publish and jf rt bp commands use the default server unless you pass --server-id=<your-server-id> explicitly.


Build-Info Flags in Native Mode

The following flags are available on every build-tool command that supports build-info collection. They work in both Wrapped Mode and Native Mode.

FlagDefaultDescription
--build-nameA name for this build (for example, my-web-app). Required with --build-number.
--build-numberA number or identifier for this build run (for example, 42, $BUILD_NUMBER). Required with --build-name.
--projectJFrog Artifactory project key. Associates the build-info with a specific project.
--moduleOptional module name within the build-info. Use when a single build produces artifacts from multiple modules. Requires --build-name and --build-number.
📘

Note

--build-name and --build-number must always be provided together. If you supply one without the other, the CLI returns an error.

--module Flag

The --module flag is used when a single build produces multiple logical components:

jf mvn clean install --build-name=my-app --build-number=1 --module=backend
jf mvn clean install --build-name=my-app --build-number=1 --module=frontend
jf rt build-publish my-app 1 --server-id=<your-server-id>

The resulting build-info for build my-app #1 contains two modules (backend and frontend), each with their own dependency trees.

📘

Note

jf rt build-publish uses your default configured server. If the build tool was configured with a different server, pass --server-id=<your-server-id> to target the correct server.

📘

Note

The --module flag is functional for all build-tool commands. For some commands (Maven, Gradle), it does not appear in jf <tool> --help output but still works when passed on the command line.

🚧

Known CLI limitation

jf npm install --help does not display build-info flags (--build-name, --build-number, --module, --project). These flags are supported and work correctly — check jf npm publish --help to see them listed, or refer to this page.

--project Flag

The --project flag associates the build-info with a JFrog Project — an organizational unit in the JFrog Platform that groups repositories, builds, and security policies.

jf npm install --build-name=my-app --build-number=1 --project=my-team
jf rt build-publish my-app 1 --project=my-team --server-id=<your-server-id>
📘

Note

The JFrog Project (--project) must already exist in Artifactory before publishing. Create projects in the JFrog Platform UI under Projects.


Wrapped Mode vs Native Mode

AspectWrapped Mode (Default)Native Mode
Repository configurationInjected by JFrog CLI from .jfrog/projects/*.yamlYou must configure manually
Project file modificationsCLI may modify files such as settings.xml, pyproject.toml, or .npmrcNo project files are modified
Build-info collectionAutomatic when --build-name and --build-number are providedSupported for Maven, Gradle, npm, Poetry, Docker, Yarn, uv, Helm, and Conan when --build-name and --build-number are provided via jf <tool>
Lock file changesPossible (for example, poetry.lock may be updated)Never modified
Requires *-config commandYes — run jf <tool>-config firstNo — config is ignored
Requires Artifactory Set Me UpOptionalRequired

Which Tools Support Native Mode?

Package ManagerHow to EnableBuild-Info in Native?Notes
Mavenexport JFROG_RUN_NATIVE=trueYes (single-module only)Bypasses mvn-config and .jfrog/ YAML. No settings.xml injection. Configure Maven manually. Multi-module projects are not supported. See Maven Native Mode.
Gradleexport JFROG_RUN_NATIVE=trueYesBypasses gradle-config and .jfrog/ YAML. No Artifactory plugin injection. Pass --server-id for server resolution.
npmexport JFROG_RUN_NATIVE=true (or deprecated --run-native flag)YesBypasses npm-config. Uses your .npmrc. Build-info still works.
Poetryexport JFROG_RUN_NATIVE=trueYesBypasses poetry-config and .jfrog/ YAML. No pyproject.toml source injection. No poetry.lock changes. Build-info works via jf poetry.
Dockerexport JFROG_RUN_NATIVE=trueYesFor jf docker build: runs native Docker build directly. Build-info is still collected when --build-name and --build-number are provided.
Yarnexport JFROG_RUN_NATIVE=true (requires Yarn 4.0.0+)YesBypasses yarn-config. Uses the project's own .yarnrc.yml authentication. With Yarn 2.x or 3.x installed, the CLI logs a warning and falls back to configured-registry mode instead.

Native-only tools (build execution always runs native. The table's "Wrapped" concept doesn't apply to how jf <tool> itself runs):

Package ManagerBuild-Info in Native?Notes
HelmYesAlways runs native Helm. Configure via helm registry login or native Helm commands.
ConanYesAlways runs native Conan. Configure via manual conan remote add, or optionally via jf conan-config (see Configuration: jf conan-config).
uvYesAlways runs native uv. Configure via [[tool.uv.index]] in pyproject.toml and jf config. No jf uv-config.

Wrapped-only tools (no Native Mode support):

pip, Pipenv, Twine, Go, NuGet, .NET, Terraform, Ruby — these tools operate exclusively in Wrapped Mode.


Maven Native Mode

When JFROG_RUN_NATIVE=true is set, jf mvn runs Maven without injecting a generated settings.xml or applying .jfrog/projects/maven.yaml. You must configure Maven to resolve from Artifactory yourself using the Artifactory Set Me Up instructions for your Maven repository. The Set Me Up page generates a <server> entry with your Artifactory URL and credentials that you add to your ~/.m2/settings.xml.

🚧

Known limitation — multi-module Maven projects

Maven Native Mode does not support multi-module Maven projects (parent POMs with <modules>). Build-info collection covers only the root pom.xml, so dependencies and artifacts from child modules may be missing or incorrect. For multi-module projects, use Wrapped Mode: run jf mvn-config, then jf mvn without JFROG_RUN_NATIVE=true.

❗️

Important — existing mvn-config users

If you have previously run jf mvn-config, a .jfrog/projects/maven.yaml file exists in your project. When this file is present, JFROG_RUN_NATIVE=true is currently ignored and the CLI falls back to Wrapped Mode silently.

To switch Maven to Native Mode when .jfrog/projects/maven.yaml exists:

  1. Remove the wrapped-mode project file:

    rm .jfrog/projects/maven.yaml
  2. Enable Native Mode for the shell session:

    export JFROG_RUN_NATIVE=true

Usage

To run a Maven build in Native Mode:

  • Run:

    export JFROG_RUN_NATIVE=true
    jf mvn clean install --build-name=my-app --build-number=1 --server-id=<your-server-id>

    Where:

    • <your-server-id>: The JFrog CLI server ID from jf config add

    For example:

    export JFROG_RUN_NATIVE=true
    jf mvn clean install --build-name=my-app --build-number=1 --server-id=my-server

Expected output

When Native Mode is active (no .jfrog/projects/maven.yaml present), Maven runs directly and build-info is collected after the build completes:

[INFO] BUILD SUCCESS
[Info] Collecting build info for executed command...
[Info] Build info saved locally. Use 'jf rt bp my-app 1' to publish it to Artifactory.
📘

Note

After Maven finishes, the CLI collects build-info from the build output. This post-build step can take several seconds. The [Info] Build info saved locally message confirms it is complete — the command is not hung.

What changes

  • No settings.xml injection
  • No .jfrog/projects/maven.yaml is read (requires the file to be absent — see the Important callout in this section)
  • Build-info is collected after the build completes (post-execution, not via extractor injection)
  • All Maven configuration comes from your own settings.xml
  • Maven wrapper: If mvnw or mvnw.cmd exists in the project root, Native Mode uses it automatically. Otherwise, the CLI uses mvn from your PATH. There is no --use-wrapper flag in Native Mode — use jf mvn-config --use-wrapper=true in Wrapped Mode when you need explicit wrapper configuration.

Gradle Native Mode

When JFROG_RUN_NATIVE=true is set, jf gradle runs Gradle without injecting the Artifactory Gradle plugin or applying .jfrog/projects/gradle.yaml. You must configure Gradle to resolve from Artifactory yourself using the Artifactory Set Me Up instructions, which generate the repository URL and credential configuration you add to your build.gradle or gradle.properties.

❗️

Important — existing gradle-config users

If you have previously run jf gradle-config, a .jfrog/projects/gradle.yaml file exists in your project. When this file is present, you must remove it for Native Mode to take effect.

To switch Gradle to Native Mode when .jfrog/projects/gradle.yaml exists:

  1. Remove the wrapped-mode project file:

    rm .jfrog/projects/gradle.yaml
  2. Enable Native Mode for the shell session:

    export JFROG_RUN_NATIVE=true

Usage

To run a Gradle build in Native Mode:

  • Run:

    export JFROG_RUN_NATIVE=true
    jf gradle clean build --server-id=<your-server-id>

    Where:

    • <your-server-id>: The JFrog CLI server ID to use for build-info (required in Native Mode)

    For example:

    export JFROG_RUN_NATIVE=true
    jf gradle clean build --server-id=my-server
📘

Note

In Gradle Native Mode, pass --server-id to specify which configured JFrog server to use for build-info publishing. Without it, the CLI uses the default server.

What changes

  • No Artifactory Gradle plugin injection
  • No .jfrog/projects/gradle.yaml is read (requires the file to be absent — see the Important callout in this section)
  • Build-info is still collected when --build-name and --build-number are provided
  • All Gradle configuration comes from your own build scripts

npm Native Mode

When JFROG_RUN_NATIVE=true is set (or the deprecated --run-native flag is used), jf npm delegates entirely to the native npm client and uses your .npmrc for all configuration. You must configure your .npmrc with the Artifactory registry URL and authentication token using the Artifactory Set Me Up instructions for your npm repository.

Usage

To run npm commands in Native Mode:

  1. Enable Native Mode for the shell session:

    export JFROG_RUN_NATIVE=true
  2. Run install or publish (examples):

    jf npm install --build-name=my-app --build-number=1
    jf npm publish --build-name=my-app --build-number=1 --server-id=<your-server-id>

    Where:

    • <your-server-id>: The JFrog CLI server ID for publish operations when you have multiple servers configured

    For example:

    export JFROG_RUN_NATIVE=true
    jf npm install --build-name=my-app --build-number=1
    jf npm publish --build-name=my-app --build-number=1 --server-id=my-server

When Native Mode is active, the CLI confirms it at the start of execution:

[Info] Running npm in native mode (JFROG_RUN_NATIVE=true)

What changes

  • No temporary .npmrc is created by the CLI
  • Your own .npmrc is used for all configuration
  • Build-info collection still works (as with other tools in Native Mode)
  • Publishing uses the native npm publish lifecycle (prepublish, publish, postpublish scripts run normally — no renaming needed)
🚧

Deprecation notice

The --run-native flag is deprecated. Use export JFROG_RUN_NATIVE=true instead. On npm 11.x, passing --run-native may also produce npm warn Unknown cli config "--run-native" from the npm client itself — this is harmless and does not affect behaviour.

🚧

npm 11.x compatibility

In Wrapped Mode, the JFrog CLI injects always-auth and email fields into the project's .npmrc. npm 11.x treats these as deprecated configuration keys and emits npm warn Unknown project config "always-auth" on every install. These warnings are harmless. To eliminate them, use Native Mode (JFROG_RUN_NATIVE=true) with a manually configured .npmrc.

🚧

Known CLI limitation

jf npm install --help does not display build-info flags. These flags are functional — use jf npm publish --help to see them listed, or refer to the Build-Info Flags section.


Poetry Native Mode

When JFROG_RUN_NATIVE=true is set, jf poetry delegates to the native Poetry client without injecting Artifactory configuration or modifying project files. You can run Poetry commands through jf poetry (to benefit from build-info collection) or directly via poetry (without build-info). You must configure Poetry to use the Artifactory repository using the Artifactory Set Me Up instructions for your PyPI repository. The Set Me Up page generates the poetry source add command and credential configuration you add to your project.

Usage

To run Poetry with build-info in Native Mode:

  1. Enable Native Mode:

    export JFROG_RUN_NATIVE=true
  2. Run installs and publishes through jf poetry when you need build-info, or use native poetry when you do not:

    • With build-info:

      jf poetry install --build-name=my-app --build-number=1
      jf poetry publish --build-name=my-app --build-number=1
    • Without build-info:

      poetry install
      poetry build
      poetry publish -r artifactory
📘

Note

In Native Mode, you can use either jf poetry install (which delegates to native Poetry and collects build-info when --build-name/--build-number are provided) or poetry install directly (no build-info). Poetry must be configured via Artifactory's Set Me Up instructions for both approaches.

What changes

  • No tool.poetry.source entries are injected into pyproject.toml
  • No poetry update is called implicitly
  • No poetry.lock modifications
  • No .jfrog/projects/poetry.yaml is read
  • Build-info is still collected when using jf poetry with --build-name and --build-number
  • All configuration comes from Poetry's own config and Artifactory Set Me Up

Docker Native Mode

When JFROG_RUN_NATIVE=true is set, jf docker build runs the native Docker build directly instead of the legacy JFrog build flow. Build-info is still collected when --build-name and --build-number are provided. Prerequisites: the Docker daemon must be running (docker info), a JFrog server must be configured with jf config add, and you must be logged in to the Docker registry with docker login <registry> before running these commands. For details, see jf docker.

Usage

To build and push a Docker image in Native Mode:

  1. Enable Native Mode, confirm the Docker daemon is running (docker info), and log in to the registry (docker login <registry>).

  2. Run build, push, and publish build-info:

    export JFROG_RUN_NATIVE=true
    jf docker build -t <registry>/<image>:<tag> . --build-name=my-app --build-number=1
    jf docker push <registry>/<image>:<tag> --build-name=my-app --build-number=1
    jf rt bp my-app 1 --server-id=<your-server-id>

    Where:

    • <registry>: Your Artifactory Docker registry host (for example, acme.jfrog.io)
    • <image>: Image name (for example, docker-local/my-app)
    • <tag>: Image tag (for example, 1.0.0)
    • <your-server-id>: The JFrog CLI server ID for jf rt bp

    For example:

    export JFROG_RUN_NATIVE=true
    jf docker build -t acme.jfrog.io/docker-local/my-app:1.0.0 . --build-name=my-app --build-number=1
    jf docker push acme.jfrog.io/docker-local/my-app:1.0.0 --build-name=my-app --build-number=1
    jf rt bp my-app 1 --server-id=my-server

What changes

  • Docker build runs via the native Docker client (no legacy JFrog build wrapper)
  • Build-info is still collected when --build-name and --build-number are provided
  • Push, pull, and scan behave the same in both modes

Supported Client Versions

Recent JFrog CLI versions are forward-compatible with modern package manager clients. The "Max Client" column represents the highest version certified for build-info collection and Native execution without schema errors.

Package ManagerMin ClientMax Client (Certified)Build-InfoMode
Maven3.1.03.9.12+ (Rec: 3.9.x)FullWrapped and Native
Gradle5.09.0FullWrapped and Native
npm6.x11.xFullWrapped and Native
Docker17.07.027.x (28 with BuildX)FullWrapped and Native
Poetry1.2.02.0FullWrapped and Native
Conan V22.02.11+FullNative only
Helm (OCI)3.8.03.17FullNative only
NuGet / .NETCore 2.0.NET 9.0FullWrapped only
Go1.141.24FullWrapped only
pip20.x25.xFullWrapped only
uv0.8.15Latest stableFullNative only
Terraform1.01.11FullWrapped only
Yarn2.4.04.xFullWrapped and Native
📘

Notes

  • Yarn: see Which Tools Support Native Mode? for the version gate.
  • Docker BuildX supports Docker engine up to v28 for multi-platform builds.
  • Go --no-fallback default is true (VCS fallback disabled by default).

When to Use Which Mode

Use Wrapped Mode when you want:

  • Integrated Artifactory resolution with zero manual configuration
  • Automatic build-info capture
  • Managed repository configuration via JFrog CLI
  • Consistent, unified behaviour across machines and CI

Use Native Mode when you need:

  • Strict lockfile fidelity (no modifications to lockfiles such as poetry.lock or package-lock.json)
  • Zero modification to project metadata files such as pom.xml, pyproject.toml, or settings.xml
  • Full compatibility with the upstream package manager's behaviour
  • Builds that must be fully deterministic across environments
  • Custom or advanced workflows configured directly in the package manager

Environment Variable Reference

VariablePurposeDefault
JFROG_RUN_NATIVEEnables Native Mode for all supported toolsfalse (not set)

When this variable is set to true, it applies to all commands in the current shell session. Unset it or start a new session to return to Wrapped Mode.


Frequently Asked Questions

This section provides answers to frequently asked questions.

plusFAQs
Q: How do I enable Native Mode?

A: Set the environment variable JFROG_RUN_NATIVE=true before running any jf <tool> command. This applies to all supported tools in the current shell session. Unset it or open a new terminal to return to Wrapped Mode.

Q: Does Native Mode still collect build-info?

A: Yes. When you run commands through jf <tool> with --build-name and --build-number, build-info is collected in both Wrapped and Native Mode. If you run the native tool directly (for example, npm install without the jf prefix), no build-info is collected.

Q: Does Maven Native Mode support multi-module projects?

A: No. Maven Native Mode (JFROG_RUN_NATIVE=true) supports single-module projects only. For multi-module Maven projects (parent POMs with <modules>), use Wrapped Mode (jf mvn-config + jf mvn). Build-info in Native Mode for multi-module projects may be incomplete or incorrect.

Q: Which tools support Native Mode vs. Wrapped Mode only?

A: Support varies by tool: some support both modes, some are native-only, and others are wrapped-only (with a special version gate for Yarn). See Which Tools Support Native Mode? for the full breakdown.

Q: Will Native Mode modify my lockfiles or project files?

A: No. Native Mode never modifies poetry.lock, package-lock.json, pyproject.toml, settings.xml, or any other project file. This is the primary reason to choose Native Mode over Wrapped Mode.

Q: Can I use Native Mode for some tools and Wrapped Mode for others?

A: Yes. JFROG_RUN_NATIVE=true applies to all supported tools in the session. Set the variable only before the commands that should run natively, then unset it before wrapped commands.

Q: How do I migrate an existing project from Wrapped Mode to Native Mode?

A: Delete the tool's .jfrog/projects/<tool>.yaml file, configure the package manager to resolve from Artifactory manually (Artifactory Set Me Up), then set JFROG_RUN_NATIVE=true. See Maven Native Mode for the exact commands and the CLI output that confirms the switch.

Q: How can I tell that Native Mode is active?

A: For npm, the CLI prints [Info] Running npm in native mode (JFROG_RUN_NATIVE=true) at the start of each command. For Maven, check that the build output contains [Info] Collecting build info for executed command... instead of Initializing Artifactory Build-Info Recording. For Gradle and Poetry, refer to the absence of injected configuration in the build output.

📘

Note

JFROG_RUN_NATIVE is not shown in jf mvn --help or jf gradle --help. This page and the FAQ are the primary discovery path for this environment variable.


Related Topics


Did this page help you?