Skip to content

Python project detection falls back to pip install -e . for uv projects when uv.lock is gitignored #433

@basnijholt

Description

@basnijholt

Bug

agent-cli dev new falls back to pip install -e . (generic Python detection) for projects that use uv when uv.lock is gitignored and pyproject.toml doesn't contain the literal string "uv".

Reproducer

Any Python project using uv where:

  1. uv.lock is in .gitignore (common for libraries)
  2. pyproject.toml uses a different build backend (e.g., hatchling) and has no [tool.uv] section
# Setup: a minimal uv project with gitignored lockfile
mkdir /tmp/test-uv-project && cd /tmp/test-uv-project
git init
cat > pyproject.toml << 'TOML'
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["rich>=13.0.0"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
TOML
echo "uv.lock" >> .gitignore
uv sync  # creates uv.lock locally but it's gitignored
git add -A && git commit -m "init"

# Now create a worktree — uv.lock won't exist there
agent-cli dev new test-branch -a
# Output:
# → Detected Python project        ← should say "Python project with uv"
# → Running: pip install -e .       ← should run "uv sync --all-extras"
# Warning: Setup failed: pip: command not found

Real-world example: basnijholt/matrix-cli — uses uv with hatchling backend, uv.lock is gitignored, pyproject.toml contains no "uv" substring.

Root Cause

In agent_cli/dev/project.py, the detect_project_type() function checks for uv at lines 151-159:

# Python with uv
if (path / "uv.lock").exists() or (
    (path / "pyproject.toml").exists() and "uv" in (path / "pyproject.toml").read_text()
):
    return ProjectType(
        name="python-uv",
        setup_commands=["uv sync --all-extras"],
        description="Python project with uv",
    )

When uv.lock is gitignored, the worktree doesn't have it. And when pyproject.toml doesn't happen to contain the substring "uv" (no [tool.uv] section, no uv-related deps), the detection falls through to the generic Python handler at lines 192-198 which runs pip install -e ..

Suggested Fix

Add uv CLI detection as a fallback — if uv is on PATH and a pyproject.toml exists, prefer uv sync over pip install -e .:

# In the generic Python fallback:
if (path / "pyproject.toml").exists():
    # Prefer uv if available
    if shutil.which("uv"):
        return ProjectType(
            name="python-uv",
            setup_commands=["uv sync --all-extras"],
            description="Python project with uv",
        )
    return ProjectType(
        name="python",
        setup_commands=["pip install -e ."],
        description="Python project",
    )

Or alternatively, check for .python-version file (commonly created by uv init), or detect uv in the build-system requires.

Environment

  • agent-cli version: latest
  • OS: Linux
  • Python: 3.12 (managed by uv, no system pip)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions