vercel-cli packages the npm vercel
CLI for Python environments. It vendors the npm package under vercel_cli/vendor/
and uses the bundled Node.js runtime provided by nodejs-wheel-binaries
, so you can run vercel
without installing Node.js.
It provides both a command-line interface and a Python API that other libraries can use programmatically instead of resorting to subprocess calls.
- Install:
pip install vercel-cli
- Use (same arguments and behavior as the official npm CLI):
vercel --version
vercel login
vercel deploy
- Use programmatically in Python (for libraries that depend on this package):
from vercel_cli import run_vercel
# Deploy current directory
exit_code = run_vercel(["deploy"])
# Deploy specific directory with custom environment
exit_code = run_vercel(
["deploy", "--prod"],
cwd="/path/to/project",
env={"VERCEL_TOKEN": "my-token"}
)
# Check version
exit_code = run_vercel(["--version"])
- No system Node.js required: The CLI runs via the Node binary from
nodejs-wheel-binaries
(currently Node 22.x). - Vendored npm package: The
vercel
npm package (production deps only) is checked intovercel_cli/vendor/
. - Console entrypoint: The
vercel
command maps tovercel_cli.run:main
, which executesvercel_cli/vendor/dist/vc.js
with the bundled Node runtime. - Python API: The
run_vercel()
function allows other Python libraries to use Vercel CLI programmatically without subprocess calls, with secure environment variable handling.
- Python 3.8+
- macOS, Linux, or Windows supported by the Node wheels
At runtime, vercel_cli.run
locates vercel_cli/vendor/dist/vc.js
and launches it via the Node executable exposed by nodejs_wheel_binaries
. CLI arguments are passed through unchanged, while environment variables are handled securely.
When using this package as a dependency in other Python libraries, you can call Vercel CLI commands directly without using subprocess:
from vercel_cli import run_vercel
import tempfile
import os
def deploy_my_app(source_dir: str, token: str) -> bool:
"""Deploy an application to Vercel programmatically."""
with tempfile.TemporaryDirectory() as temp_dir:
# Copy your app to temp directory and modify as needed
# ...
# Deploy with custom environment
env = {
"VERCEL_TOKEN": token,
"NODE_ENV": "production"
}
exit_code = run_vercel(
["deploy", "--prod", "--yes"],
cwd=temp_dir,
env=env
)
return exit_code == 0
# Usage
success = deploy_my_app("./my-app", "my-vercel-token")
The run_vercel()
function accepts:
args
: List of CLI arguments (same as command line)cwd
: Working directory for the commandenv
: Environment variables to set (passed directly to the Node.js runtime)
When using the env
parameter, only explicitly provided environment variables are passed to the Vercel CLI. This prevents accidental leakage of sensitive environment variables from your Python process while still allowing you to set necessary variables like VERCEL_TOKEN
.
Example with secure token handling:
from vercel_cli import run_vercel
# Secure: only VERCEL_TOKEN is passed to the CLI
exit_code = run_vercel(
["deploy", "--prod"],
env={"VERCEL_TOKEN": "your-secure-token"}
)
This approach avoids common security pitfalls of subprocess environment variable handling.
There are two ways to update the vendored npm package under vercel_cli/vendor/
:
- Manual update to a specific version
# Using the console script defined in pyproject.toml
uv run update-vendor 46.0.2
# or equivalently
uv run python scripts/update_vendor.py 46.0.2
This will:
- fetch
vercel@46.0.2
from npm, - verify integrity/shasum,
- install production dependencies with
npm install --omit=dev
, and - copy the result into
vercel_cli/vendor/
.
- Automatic check-and-release (GitHub Actions)
The workflow .github/workflows/release.yml
checks npm latest
and, if newer than the vendored version, will:
- vendor the new version using
scripts/check_and_update.py
, - commit the changes and create a tag
v<version>
, - build distributions, and
- publish to PyPI (requires
PYPI_API_TOKEN
).
The Python package version is derived dynamically from the vendored package.json
via Hatch’s version source:
[tool.hatch.version]
path = "vercel_cli/vendor/package.json"
pattern = '"version"\s*:\s*"(?P<version>[^\\"]+)"'
- Build backend:
hatchling
- Dependency management:
uv
(seeuv.lock
) - Tests:
pytest
with coverage intests/
- Lint/format:
ruff
; type-check:basedpyright
Common commands (using uv
):
# Run tests with coverage
uv run pytest --cov=vercel_cli --cov-report=term-missing
# Lint and format
uv run ruff check .
uv run ruff format .
# Type-check
uv run basedpyright
# Build wheel and sdist
uv run --with build python -m build