Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,22 +129,35 @@ For command reference, see [Commands](https://pipenv.pypa.io/en/latest/commands/

### Shell Completion

To enable completion in fish, add this to your configuration `~/.config/fish/completions/pipenv.fish`:
Shell completion is powered by [argcomplete](https://kislyuk.github.io/argcomplete/).
Install the optional dependency first:

eval (env _PIPENV_COMPLETE=fish_source pipenv)
pip install "pipenv[completion]"

For **fish**, add this to `~/.config/fish/completions/pipenv.fish`:

register-python-argcomplete --shell fish pipenv | source

There is also a [fish plugin](https://github.com/fisherman/pipenv), which will automatically
activate your subshells for you!

Alternatively, with zsh, add this to your configuration `~/.zshrc`:
For **zsh**, add this to your `~/.zshrc`:

autoload -U bashcompinit
bashcompinit
eval "$(register-python-argcomplete pipenv)"

eval "$(_PIPENV_COMPLETE=zsh_source pipenv)"
For **bash** (including Git Bash on Windows), add this to `~/.bashrc` or `~/.bash_profile`:

Alternatively, with bash, add this to your configuration `~/.bashrc` or `~/.bash_profile`:
eval "$(register-python-argcomplete pipenv)"

eval "$(_PIPENV_COMPLETE=bash_source pipenv)"
Then reload your shell, and tab completions are enabled!

Magic shell completions are now enabled!
> **Note:** If you are upgrading from pipenv < 2026.5.0, the old
> `_PIPENV_COMPLETE` environment variable method no longer works.
> Replace it with the `register-python-argcomplete` commands above.
> See the [Shell Completion docs](https://pipenv.pypa.io/en/latest/shell.html#shell-completion)
> for details.

Usage
-------
Expand Down
33 changes: 33 additions & 0 deletions docs/shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,35 @@ After reloading your shell, type `pipenv ` and press `Tab` — you should see th
list of available subcommands. Pressing `Tab` again after a partial subcommand
name (e.g. `pipenv ins<Tab>`) completes it to `pipenv install`.

#### Git Bash (Windows)

Git Bash supports bash completion. Add to your `~/.bashrc` (typically
`C:\Users\<you>\.bashrc`):

```bash
eval "$(register-python-argcomplete pipenv)"
```

Then restart Git Bash or run `source ~/.bashrc`.

### Migrating from pipenv < 2026.5.0

In older versions of pipenv (before 2026.5.0), shell completion was powered by
Click and activated with the `_PIPENV_COMPLETE` environment variable:

```bash
# OLD method — no longer works in pipenv >= 2026.5.0
eval "$(_PIPENV_COMPLETE=bash_source pipenv)" # bash
eval "$(_PIPENV_COMPLETE=zsh_source pipenv)" # zsh
_PIPENV_COMPLETE=fish_source pipenv | source # fish
```

Starting with pipenv 2026.5.0, shell completion uses
[argcomplete](https://kislyuk.github.io/argcomplete/) instead. **Replace** the
lines above with the `register-python-argcomplete` commands shown in the
[Activation](#activation) section and make sure the `argcomplete` package is
installed (`pip install "pipenv[completion]"`).

### Troubleshooting

If completion is not working:
Expand All @@ -225,6 +254,10 @@ If completion is not working:
```
It should print a shell function definition without errors.

5. **If you see a migration message** about `_PIPENV_COMPLETE`, you are using
the old activation method. See [Migrating from pipenv < 2026.5.0](#migrating-from-pipenv--202650)
above.

## Best Practices for Shell Configuration

### Proper PATH Configuration
Expand Down
17 changes: 17 additions & 0 deletions pipenv/cli/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,23 @@ def cli():
from pipenv.utils.shell import system_which
from pipenv.utils.virtualenv import do_where, warn_in_virtualenv

# Handle legacy _PIPENV_COMPLETE env var from the Click-based CLI.
# Since pipenv 2026.5.0, shell completion uses argcomplete instead.
# Detect the old mechanism and provide a helpful migration message.
if os.environ.get("_PIPENV_COMPLETE"):
print(
"Shell completion has changed in pipenv >= 2026.5.0.\n"
"The _PIPENV_COMPLETE environment variable is no longer supported.\n"
"\n"
"To enable shell completion, install the completion extra and use:\n"
" pip install pipenv[completion]\n"
' eval "$(register-python-argcomplete pipenv)"\n'
"\n"
"For more details, see: https://pipenv.pypa.io/en/latest/shell.html#shell-completion",
file=sys.stderr,
)
sys.exit(1)

parser = build_parser()

# Enable shell completion when argcomplete is installed.
Expand Down
44 changes: 38 additions & 6 deletions pipenv/routines/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import logging
import subprocess
import sys
import tempfile

from pipenv.utils import console, err
from pipenv.utils.processes import run_command
Expand Down Expand Up @@ -115,9 +116,9 @@ def build_audit_options(
if aliases:
options.append("--aliases")

# Use lockfile (pyproject.toml / pylock.toml)
if use_lockfile:
options.append("--locked")
# Note: use_lockfile is handled in do_audit by generating a temporary
# requirements file from Pipfile.lock, since pip-audit's --locked flag
# does not support Pipfile.lock format.

# Requirements file
if requirements_file:
Expand Down Expand Up @@ -165,7 +166,7 @@ def do_audit( # noqa: PLR0913

Supports auditing from:
- The current virtualenv (default)
- pyproject.toml / pylock.toml files (with --locked flag)
- Pipfile.lock (with --locked flag, converted to requirements format for pip-audit)
"""
if not verbose:
logging.getLogger("pipenv").setLevel(logging.ERROR if quiet else logging.WARN)
Expand Down Expand Up @@ -222,9 +223,35 @@ def do_audit( # noqa: PLR0913
python_path = project_python(project, system=system)
cmd = [python_path, "-m", "pip_audit"] + options

# If using lockfile mode, add the project directory path
# If using lockfile mode, generate a temporary requirements file from
# Pipfile.lock and pass it via -r. pip-audit's own --locked flag only
# recognises pylock.toml / poetry.lock / uv.lock — not Pipfile.lock.
tmp_requirements = None
if use_lockfile:
cmd.append(project.project_directory)
if not project.lockfile_exists:
err.print(
"[red]Pipfile.lock not found. Run 'pipenv lock' first.[/red]"
)
sys.exit(1)

from pipenv.utils.requirements import requirements_from_lockfile

lockfile = project.load_lockfile(expand_env_vars=False)
deps = {}
deps.update(lockfile.get("default", {}))
deps.update(lockfile.get("develop", {}))

lines = requirements_from_lockfile(
deps, include_hashes=False, include_markers=True
)

tmp_requirements = tempfile.NamedTemporaryFile(
mode="w", suffix=".txt", prefix="pipenv-audit-", delete=False
)
tmp_requirements.write("\n".join(lines))
tmp_requirements.flush()
tmp_requirements.close()
cmd.extend(["-r", tmp_requirements.name])

if not quiet and not project.s.is_quiet() and verbose:
console.print(f"[dim]Running: {' '.join(cmd)}[/dim]")
Expand All @@ -240,3 +267,8 @@ def do_audit( # noqa: PLR0913
except Exception as e:
err.print(f"[red]Error running pip-audit: {str(e)}[/red]")
sys.exit(1)
finally:
if tmp_requirements is not None:
import os

os.unlink(tmp_requirements.name)
Loading