Use Poetry with JFrog CLI
Run Poetry commands with Artifactory integration and optional build-info collection.
This topic covers the following tasks:
When to Use
Use jf poetry if your Python project uses Poetry (with pyproject.toml) for dependency management. For pip-based projects, use jf pip. For Pipenv-based projects, use jf pipenv.
Prerequisites
- Poetry must be installed and available on your
$PATH.- Recommended:
pipx install poetry(automatically adds Poetry to your PATH). - pip:
pip install poetry— on macOS, pip installs Poetry to~/Library/Python/X.Y/bin/which is not on$PATHby default. After installing, run:Add this line to your shell profile (export PATH="$PATH:$(python3 -m site --user-base)/bin"~/.zshrcor~/.bashrc) to make it permanent.
- Recommended:
- Run
jf poetry-configin the project directory before the first install (Wrapped Mode only). - Configure a server with
jf config addorjf c add. - Authentication to Artifactory is required.
- For Native Mode, configure Poetry via Artifactory's Set Me Up instructions instead.
Configuration: jf poetry-config
jf poetry-configGenerate Poetry build configuration for dependency resolution. Run this once per project before your first install.
To configure Poetry for Artifactory:
- From your project directory, run
jf poetry-configwith your Artifactory server ID and PyPI resolution repository (see Non-Interactive Configuration with Flags). - Confirm the generated config under
.jfrog/projects/poetry.yaml(see How to Verify).
Synopsis
jf poetry-config [options]
Aliases: poc
Configuration Options
| Flag | Default | Description |
|---|---|---|
--global | false | Set to true for global configuration (all projects). Specific projects can override. |
--repo-resolve | — | Repository for dependencies resolution |
--server-id-resolve | — | Artifactory server ID for resolution. Configure with jf config add. |
Configuration Examples
View Help
jf poetry-config --helpNon-Interactive Configuration with Flags
jf poetry-config --server-id-resolve=<server-id> --repo-resolve=<repo-name>Where:
- <server-id>: The server ID configured using
jf config add - <repo-name>: The name of the PyPI repository in Artifactory
For example:
jf poetry-config --server-id-resolve=my-server --repo-resolve=pypi-virtualWhy Run Config First?
You must run jf poetry-config before jf poetry install (Wrapped Mode only). The config creates .jfrog/projects/poetry.yaml for dependency resolution through Artifactory. Without it, jf poetry does not know where to fetch packages.
Shortcut
: In CI/CD, pass all flags non-interactively so the config step is fully automated and reproducible.
Configuration Notes
- Config sets resolution only:
jf poetry-configconfigures dependency resolution but not a deployer repository. To publish, pass--repositorydirectly onjf poetry publish(Wrapped Mode) or use nativepoetry publish(Native Mode). - Run once per project: Re-run when changing the resolution repository.
Expected Output
$ jf poetry-config --server-id-resolve=my-server --repo-resolve=pypi-virtual
[Info] poetry build config successfully created.
How to Verify
After running, confirm the configuration exists:
cat .jfrog/projects/poetry.yamlExpected file contents:
version: 1
type: poetry
resolver:
repo: pypi-virtual
serverId: my-serverBuild: jf poetry
jf poetryRun Poetry commands with Artifactory integration and optional build-info collection.
To run Poetry with Artifactory integration:
- Ensure
jf poetry-confighas been run in the project directory when using Wrapped Mode (see Configuration). - Run
jf poetrywith the Poetry subcommand and arguments you need, adding--build-nameand--build-numberwhen you want build-info (see Build Examples).
Synopsis
jf poetry <poetry-arguments> [options]
Aliases: none
Arguments
| Argument | Required | Description |
|---|---|---|
<poetry-arguments> | Yes | Arguments and options for the poetry command (for example, install, add) |
Build Options
| Flag | Default | Description |
|---|---|---|
--build-name | — | Build name for build-info. Requires --build-number. |
--build-number | — | Build number for build-info. Requires --build-name. |
--module | — | Optional module name for build-info. Requires --build-name and --build-number. |
--project | — | JFrog Artifactory project key |
Build Examples
Help
jf poetry --helpNote
jf poetry --helppasses--helpthrough to the native Poetry client and shows Poetry's own help page. JFrog-specific flags (--build-name,--build-number,--module,--project) are intercepted by JFrog CLI and do not appear in Poetry's help output. Refer to the Build Options table above for JFrog-specific flags.
Install with Build-Info
jf poetry install --build-name=my-app --build-number=1Expected output (Wrapped Mode):
[Info] Running Poetry install.
[Info] Added tool.poetry.source name:"<repo-name>" url:"https://<server>/artifactory/api/pypi/<repo-name>"
[Info] Running Poetry update
Updating dependencies
Resolving dependencies...
Writing lock file
Note
In Wrapped Mode, JFrog CLI automatically injects a
[[tool.poetry.source]]entry into yourpyproject.tomland may runpoetry updateto resolve dependencies. This is expected behaviour and will modifypoetry.lock. Switch to Native Mode if you require a fully deterministic lockfile.
Add Dependencies
jf poetry add <package-name>Poetry Execution Modes
JFrog CLI supports two execution modes for Poetry.
Wrapped Mode (Default)
- Uses
jf poetry-configsettings - Injects
tool.poetry.sourceentries intopyproject.toml - May call
poetry updateduring dependency resolution - May modify
poetry.lock - Automatically collects build-info when provided
--build-name/--build-number
Native Mode
Enable using:
export JFROG_RUN_NATIVE=true
In Native Mode, JFrog CLI:
- Delegates to the native Poetry client without injecting configuration
- Does not inject
tool.poetry.sourceintopyproject.toml - Does not call
poetry update - Does not modify
poetry.lock - Does not apply
jf poetry-configvalues or JFrog CLI YAML (.jfrog/projects/*.yaml) configuration - Relies entirely on Poetry's own configuration (as set via Artifactory Set Me Up)
- Still collects build-info when
--build-nameand--build-numberare provided viajf poetry - Ensures deterministic, reproducible builds
Prerequisite for Native Mode
Your
pyproject.tomlmust contain a[[tool.poetry.source]]entry pointing to your Artifactory PyPI repository for Native Mode to route traffic through Artifactory. This entry can be added manually or will already be present if you previously ran a Wrapped Mode install. You can also add it via Artifactory's Set Me Up instructions.
Install: Wrapped vs Native
Wrapped Mode Install
jf poetry install --build-name=my-python-app --build-number=1.2.0Wrapped Mode behaviour:
- May implicitly run
poetry update - May modify
poetry.lock - May inject repository sources into
pyproject.toml
Use Native Mode if you require full lockfile fidelity.
Native Mode Install
export JFROG_RUN_NATIVE=true
# With build-info collection
jf poetry install --build-name=my-python-app --build-number=1.2.0
# Or directly (no build-info)
poetry installNote
In Native Mode, you can use either
jf poetry install(which delegates to native Poetry and collects build-info when--build-name/--build-numberare provided) orpoetry installdirectly (no build-info). Poetry must be configured via Artifactory's Set Me Up instructions to authenticate and resolve from Artifactory.
Publish: Wrapped vs Native
Wrapped Mode Publish
jf poetry publish --repository pypi-local --no-interaction --build-name=my-python-app --build-number=1.2.0Important
Use
--repository(Poetry's native flag, also available as-r) to specify the target repository. The--no-interactionflag suppresses Poetry's confirmation prompt (Build anyway? (yes/no)) when existing dist files are present — this is required in CI/CD environments where no TTY is available.
Behaviour:
- May inject
tool.poetry.sourceintopyproject.toml - May update dependency metadata
Use Native Mode to prevent any modifications.
Native Mode Publish
export JFROG_RUN_NATIVE=true
# With build-info collection
jf poetry publish --no-interaction --build-name=my-python-app --build-number=1.2.0
# Or directly (no build-info)
poetry build
poetry publish --no-interaction -r <REPO_ALIAS>Credentials must be configured via Set Me Up.
Environment Variable
| Variable | Purpose | Default |
|---|---|---|
JFROG_RUN_NATIVE | Enables Native Mode and bypasses Wrapped Mode entirely | false |
FAQ
Q: Does jf poetry-config affect Native Mode?
A: No — Native Mode ignores jf poetry-config and YAML.
Q: Can Native Mode collect build-info?
A: Yes — when you use jf poetry with --build-name and --build-number, build-info is collected even in Native Mode. If you run poetry directly (without the jf prefix), no build-info is collected.
For a cross-tool comparison of Native Mode across Maven, Gradle, npm, and Poetry, see the dedicated Native Mode page.
Universal Package Note
JFrog CLI is a pass-through to Poetry for execution and output. Output format/behaviour belongs to Poetry; if Poetry changes its output in a newer version, JFrog CLI would simply honour that without any custom adjustment.
Note
The
jf poetry-configconfiguration is used only in Wrapped Mode. Native Mode ignores this entirely.
Important Notes
- Config required first: Run
jf poetry-configin the project directory before your first install (Wrapped Mode only). - Resolution only: Poetry config currently supports dependency resolution. For publishing, use
jf poetry publish(Wrapped Mode) or Poetry's nativepoetry publish(Native Mode). - Poetry commands: All standard Poetry arguments work (
install,add,update,lock, and others). - Build-info: Use
--build-nameand--build-number, then publish withjf rt build-publish.
CI/CD Example (GitHub Actions)
# .github/workflows/build.yml
steps:
- uses: actions/checkout@v4
- name: Setup JFrog CLI
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.JF_URL }}
JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install Poetry
run: |
pip install poetry
echo "$(python3 -m site --user-base)/bin" >> $GITHUB_PATH
- name: Configure Poetry
run: jf poetry-config --server-id-resolve=setup-jfrog-cli-server --repo-resolve=pypi-virtual
- name: Install dependencies
run: jf poetry install --build-name=my-python-app --build-number=${{ github.run_number }}
- name: Publish package
run: jf poetry publish --repository pypi-local --no-interaction --build-name=my-python-app --build-number=${{ github.run_number }}
- name: Publish build info
run: jf rt build-publish my-python-app ${{ github.run_number }}Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
command not found: poetry | Poetry not on $PATH (common after pip install) | Add Poetry to PATH: export PATH="$PATH:$(python3 -m site --user-base)/bin". Use pipx install poetry to avoid this permanently. |
no config file was found | jf poetry-config was not run (Wrapped Mode) | Run jf poetry-config in the project directory |
404 on jf poetry install | Resolution repository does not exist or name is wrong | Verify the repo name matches an existing PyPI virtual repository in Artifactory |
| 401 / 403 errors | Invalid credentials or insufficient permissions | Re-run jf config add with a valid access token |
poetry.lock modified unexpectedly | Wrapped Mode may run poetry update implicitly | Switch to Native Mode (export JFROG_RUN_NATIVE=true) for lockfile fidelity |
The option "--repo" does not exist | --repo is not a valid flag for jf poetry publish | Use --repository (or -r) instead: jf poetry publish --repository <local-repo-name> --no-interaction ... |
jf poetry publish hangs on Build anyway? (yes/no) | Poetry prompts for confirmation when dist files exist | Add --no-interaction to the publish command to suppress the prompt |
jf poetry publish fails with "repo not configured" | No target repository specified | Pass --repository <local-repo-name> directly on the publish command |
[Warn] couldn't extract payload from Access Token | Using a JFrog Platform reference token (non-JWT) | This warning is informational only — commands still authenticate correctly. If using basic auth, provide a username via jf config add. |
| Native Mode not resolving from Artifactory | No [[tool.poetry.source]] in pyproject.toml | Add a source entry manually or run a Wrapped Mode install first; alternatively, configure Poetry via Artifactory's Set Me Up |
Enable debug logging: export JFROG_CLI_LOG_LEVEL=DEBUG
Related Topics
- Build Tools Overview — Capabilities matrix and tool reference
- Native Mode — Supported packages with Native Mode
Updated about 1 month ago
