install.sh picks `python3` without a version check; requirements.txt needs >=3.10 (fails on macOS system Python 3.9.6)
Summary
install.sh selects the first python3 on PATH without checking its version, but requirements.txt requires Python ≥ 3.10. On macOS, /usr/bin/python3 is the system Python 3.9.6, so the install reliably fails at the dependency step.
The prerequisite check also advertises Python 3.8+, which is not achievable with the current pins.
Environment
- macOS (Apple Silicon), zsh
- System Python: 3.9.6 (
/usr/bin/python3) - Homebrew Python 3.12.13 present, but only as
python3.12(nopython3symlink onPATH) - git 2.49.0, Claude Code CLI present,
uvnot installed
Reproduction
curl -fsSL https://raw.githubusercontent.com/zubair-trabzada/geo-seo-claude/main/install.sh | bashOutput (trimmed):
✓ Python found: Python 3.9.6
→ Creating isolated Python environment → /Users/<user>/.claude/skills/geo/.venv
✓ Virtual environment created
→ Installing Python dependencies into venv...
ERROR: Ignored the following versions that require a different python version: 12.1.0 Requires-Python >=3.10; ...
ERROR: Could not find a version that satisfies the requirement Pillow<13.0.0,>=12.1.0
ERROR: No matching distribution found for Pillow<13.0.0,>=12.1.0
✗ Failed to install dependencies.Root cause
In install.sh, the python3 branch sets PYTHON_CMD with no version gate:
if command -v python3 &> /dev/null; then
PYTHON_CMD="python3" # <-- no version check
elif command -v python &> /dev/null; then
...
if [ "$MAJOR" -ge 3 ] && [ "$MINOR" -ge 8 ]; then # <-- only the fallback checks
PYTHON_CMD="python"
fi
fiNote the asymmetry: the python fallback validates the version, but the far more common python3 path does not. The venv is then created with 3.9.6, and requirements.txt cannot resolve:
| Pin | Requires |
|---|---|
Pillow>=12.1.0,<13.0.0 |
≥ 3.10 |
lxml>=6.0.2,<7.0.0 |
≥ 3.10 |
playwright>=1.56.0,<2.0.0 |
≥ 3.10 |
So the stated "Python 3.8+" prerequisite is unsatisfiable in practice; the real floor is 3.10.
Secondary impact: aborting here leaves a half-configured install
This is worth flagging because the failure is more than a missing-deps message. The dependency failure does exit 1, which skips the two steps that follow:
- "Pinning script shebangs to venv interpreter"
- "Rewriting skill & agent references to use the venv"
The skills/agents are already copied into ~/.claude at that point, still referencing bare python3. The result is an installed-looking skill whose commands fail later with a misleading:
ERROR: Required packages not installed. Run: pip install -r requirements.txtRunning pip install -r requirements.txt as suggested doesn't help, because the problem is the interpreter version, not a missing install step. This sends users down the wrong path.
Suggested fix
Probe for a ≥3.10 interpreter rather than taking python3 blindly:
PYTHON_CMD=""
for candidate in python3.13 python3.12 python3.11 python3.10 python3 python; do
command -v "$candidate" &> /dev/null || continue
if "$candidate" -c 'import sys; sys.exit(0 if sys.version_info >= (3, 10) else 1)' 2>/dev/null; then
PYTHON_CMD="$candidate"
break
fi
done
if [ -z "$PYTHON_CMD" ]; then
print_error "Python 3.10+ is required (found: $(python3 --version 2>&1 || echo none))."
echo " macOS: brew install [email protected]"
exit 1
fiThis fails early with an accurate message instead of after the venv is built and files are copied.
Two smaller points:
- Update the "Python 3.8+ is required" string (and any README mention) to 3.10+ so it matches the pins.
- Consider whether the dependency failure should roll back or warn that
~/.claudenow holds a partially configured skill, rather than exiting silently mid-install.
Workaround for anyone hitting this
Point python3 at a 3.10+ interpreter for the duration of the install:
brew install [email protected]
mkdir -p /tmp/pybin && ln -sf "$(brew --prefix)/bin/python3.12" /tmp/pybin/python3
PATH="/tmp/pybin:$PATH" bash install.shVerified on macOS with Python 3.12.13: all 25 dependencies install, shebangs pin correctly, markdown references rewrite, and fetch_page.py / citability_scorer.py run against live URLs.
Source: zubair-trabzada/geo-seo-claude