Use Poetry with JFrog CLI
Configure and run jf poetry with JFrog Artifactory for Wrapped and Native Mode builds and build-info.
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. For uv-managed projects, use jf uv.
Package Alias (Ghost Frog)
To run native
poetrycommands without thejfprefix, see Use JFrog CLI Package Alias.
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
Generate 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 usingjf 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
Run 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 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 behavior and modifiespoetry.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 it will already be present if you previously ran a Wrapped Mode install. You can also add it using 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 behavior:
- 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-nameand--build-numberare provided) orpoetry installdirectly (no build-info). Poetry must be configured using 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 flag is required in CI/CD environments where no TTY is available.
Behavior:
- 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 |
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 and behavior belong to Poetry. If Poetry changes its output in a newer version, JFrog CLI honors 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
Package Alias (Ghost Frog)
To run
poetrywithout thejfprefix, enable Package Alias insetup-jfrog-cliand setJFROG_CLI_GHOST_FROG=true. If you install the tool after the action (for examplesetup-javaorsetup-node), re-pin the alias path toGITHUB_PATH. See Use JFrog CLI Package Alias.
# .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 using Artifactory's Set Me Up |
Enable debug logging: export JFROG_CLI_LOG_LEVEL=DEBUG
Frequently Asked Questions
This section provides answers to frequently asked questions about using Poetry with JFrog CLI.
FAQs
Q: Does jf poetry-config affect Native Mode?
A: No. Native Mode ignores jf poetry-config and the .jfrog/projects/poetry.yaml configuration entirely. See Native Mode.
Q: Can Native Mode collect build-info?
A: Yes, when you run jf poetry (not native poetry) with --build-name and --build-number. See Build-Info Flags in Native Mode for details across all tools.
Related Topics
Updated 3 days ago
