name: sync-deps description: 'Synchronises all dependency files from the actual imports in the codebase. Use when asked to "update requirements.txt", "sync dependencies", "update pyproject.toml dependencies", "fix requirements", "update deps", "sync deps", "update dependency files", or "update renv/environment.yml". Scans all Python source files for third-party imports, resolves PyPI package names, fetches installed versions, then writes requirements.txt and updates pyproject.toml [project.dependencies] — keeping every dep file in sync with a single source of truth.'
Sync Dependencies
Derives the project's dependency list from actual imports in source files — one
scan, one canonical list, propagated to every dep file. No manual bookkeeping;
no drift between requirements.txt and pyproject.toml.
When to Use This Skill
- User says "update requirements.txt", "sync deps", "fix requirements", "update deps"
- User says "update pyproject.toml dependencies", "sync dependency files"
- After adding or removing a package to the project
- Before a release or a code review
Single Source of Truth
source files (.py, .ipynb)
│
▼
sync_deps.py ← ONE scan, ONE canonical list
│
├──▶ requirements.txt
├──▶ pyproject.toml [project.dependencies]
├──▶ environment.yml (if present)
└──▶ setup.cfg (if present)
Everything is derived; never edit dep files by hand.
Step 1 — Run the scanner
Run the bundled script from the repo root (not from inside the skill folder):
python .claude/skills/sync-deps/scripts/sync_deps.py
The script outputs one package>=X.Y line per third-party dependency, sorted
alphabetically, to stdout. Capture it:
python .claude/skills/sync-deps/scripts/sync_deps.py > /tmp/deps_raw.txt
Inspect the output before writing anything. If a package is missing or wrong,
update IMPORT_TO_PACKAGE in the script — that is the only place to change.
Step 2 — Write requirements.txt
Replace the full content of requirements.txt at the repo root with:
# Runtime dependencies — generated by sync-deps, do not edit by hand.
# Regenerate with: python .claude/skills/sync-deps/scripts/sync_deps.py
#
<one line per package from stdout, sorted>
Rules:
- Keep the header comment exactly as shown.
- Packages are sorted case-insensitively.
- Dev-only packages (
pytest,mypy,ruff,pytest-cov) must not appear here — they belong inpyproject.toml [project.optional-dependencies].devonly.
Step 3 — Update pyproject.toml [project.dependencies]
Read pyproject.toml. Replace the dependencies = [...] list under [project]
with the same package list from Step 1, formatted as TOML strings:
dependencies = [
"package-a>=X.Y",
"package-b>=X.Y",
]
Rules:
- Preserve all other sections unchanged (surgical edit only).
- Dev packages stay in
[project.optional-dependencies].dev— do not move them. - If
[project.optional-dependencies].devis missing, add it with at minimum:["pytest>=8", "pytest-cov", "mypy", "ruff"].
Step 4 — Update optional dep files (if present)
Scan the repo root for these files and update them if found:
environment.yml (conda)
Update the dependencies: list. Preserve - pip: sub-list structure.
Example shape:
dependencies:
- python>=3.9
- pip:
- package-a>=X.Y
- package-b>=X.Y
setup.cfg
If install_requires exists under [options], replace it with the new list:
[options]
install_requires =
package-a>=X.Y
package-b>=X.Y
Pipfile
If present, update the [packages] section. Do not modify [dev-packages].
Step 5 — Verify and report
After all edits, print a summary:
sync-deps complete
─────────────────────────────────────────
Source files scanned : <N> .py files, <M> .ipynb files
Third-party imports : <K>
─────────────────────────────────────────
Updated:
requirements.txt — <N> packages
pyproject.toml — [project.dependencies] (<N> entries)
environment.yml — (skipped — not found)
setup.cfg — (skipped — not found)
─────────────────────────────────────────
Packages:
<sorted package list, one per line>
Import-to-Package Name Map
The script maintains IMPORT_TO_PACKAGE — a dict mapping Python import names
to their canonical PyPI package names. This is the only place to fix
name mismatches. Never hardcode a mapping elsewhere.
| Import name | PyPI package |
|---|---|
sklearn | scikit-learn |
PIL | Pillow |
cv2 | opencv-python |
yaml | PyYAML |
bs4 | beautifulsoup4 |
dotenv | python-dotenv |
faiss | faiss-cpu |
rank_bm25 | rank-bm25 |
langchain_classic | langchain-classic |
langchain_core | langchain-core |
langchain_community | langchain-community |
langchain_openai | langchain-openai |
To add a new mapping: edit IMPORT_TO_PACKAGE in scripts/sync_deps.py.
Exclusion Rules
These are never added to requirements.txt:
- Standard library modules (
os,sys,json, …) - The project's own package (auto-detected from
pyproject.toml [project].name) - Dev-only packages:
pytest,pytest-cov,mypy,ruff,black,isort - Private names (starting with
_) - Modules in excluded directories:
venv/,.venv/,build/,dist/,.eggs/
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Package missing from output | Import name not in IMPORT_TO_PACKAGE and not installed | Add mapping to IMPORT_TO_PACKAGE or install the package |
| Wrong version shown | Package not installed in active venv | Activate the correct venv before running |
sys.stdlib_module_names not available | Python < 3.10 | Script falls back to a static stdlib set; update Python if possible |
| Package appears but shouldn't | Import from a test fixture or example that shadows a real name | Add it to DEV_ONLY_PACKAGES in the script |
pyproject.toml parse error | Non-standard TOML formatting | Read the file carefully and apply a surgical edit |