MLOps Initialization
SkillDev toolsInitialize a production-ready Python MLOps project with uv, git, mise, and a shared editor setup. Use when starting a new repository, writing its first pyproject.toml, or repairing an inconsistent project skeleton.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the MLOps Initialization skill
What this skill tells your AI
The instructions your AI receives, as published by mlops-courses/mlops-coding-skills in mlops-initialization/SKILL.md and read by ahel’s review.
Goal
To initialize a robust, production-ready MLOps project structure using the modern Python toolchain (uv), industry-standard version control (git), a shared task runner (mise), and a configured development environment (VS Code). This skill ensures reproducibility, collaboration, and high code quality from day one.
Prerequisites
- Language: Python 3.14 (latest stable)
- Manager:
uv(replaces pip, venv, poetry, pyenv) - Tasks:
mise(replaces make/just, and pins the toolchain) - VCS: Git
- IDE: VS Code (recommended)
Instructions
1. System & Toolchain Verification
Before modifying files, verify that the essential tools are available.
- Check
uv:- Ensure
uvis installed:uv --version - If missing, install it:
curl -LsSf https://astral.sh/uv/install.sh | sh
- Ensure
- Check
git:- Ensure
gitis installed:git --version
- Ensure
- Check
mise:- Ensure
miseis installed:mise --version misepins every non-Python tool (dprint,gitleaks,trivy,actionlint, ...) so contributors and CI resolve identical binaries.
- Ensure
2. Project Initialization
Initialize the project structure using uv to ensure modern standards (pyproject.toml).
- Create Directory (if not already inside):
mkdir <project_name> && cd <project_name>
- Initialize Project:
- Run
uv init - This creates
pyproject.toml,.python-version, and a basichello.py.
- Run
- Configure
pyproject.toml:-
Update metadata:
name,version,description,authors,license. -
Set requires-python: Ensure it matches the project's target environment (e.g.,
>=3.14). -
Declare the license the PEP 639 way:
licenseis an SPDX expression (a plain string), and the file itself is listed inlicense-files. The oldlicense = { file = "LICENSE" }table form is deprecated and rejected by current build backends. -
Example Structure:
[project] name = "my-mlops-project" version = "0.1.0" description = "A robust MLOps project." readme = "README.md" requires-python = ">=3.14" license = "MIT" # SPDX expression (PEP 639) license-files = ["LICENSE.txt"] # the file(s) shipped in the distribution authors = [{ name = "Your Name", email = "your.email@example.com" }] dependencies = [ "loguru>=0.7.3", "mlflow>=3.15.1", # MLflow 3.15 still declares `pandas<3`, so the pandas 3.x line is unreachable # here; keep the floor permissive and let `uv.lock` pin the tested version. "pandas>=2.3.3", "pydantic>=2.13.4", "scikit-learn>=1.9.0", ] [project.urls] Repository = "https://github.com/username/my-mlops-project" Documentation = "https://username.github.io/my-mlops-project" # PEP 735 dependency groups (not shipped with the package). [dependency-groups] dev = [ "lefthook>=2.1.10", "pip-audit>=2.10.1", "pytest>=9.1.1", # Ruff 0.16 rewrote the default rule set and now formats Python inside Markdown: # an older Ruff disagrees with a 0.16-formatted repository, so floor it here. "ruff>=0.16.2", "ty>=0.0.69,<0.1", # pre-1.0: pin a compatible range ] [build-system] # Keep the upper bound at least one minor ahead of the pinned `uv`: without it # `uv build` warns, and a future breaking `uv_build` silently breaks the sdist. requires = ["uv_build>=0.9,<0.13"] build-backend = "uv_build"
-
3. Dependency Management
Establish a clean separation between production and development dependencies.
- Add Runtime Dependencies (Production):
- Use
uv add <package>for libraries needed in production (e.g.,mlflow,pandas,scikit-learn). - These go into
[project.dependencies]inpyproject.toml.
- Use
- Add Dev Dependencies (Development):
- Use
uv add --dev <package>(or--group dev) for tools likepytest,ruff,ty. - These go into
[dependency-groups](PEP 735) and are kept out of production builds.
- Use
- Sync Environment:
- Run
uv syncto resolve dependencies, create the.venv, and generate theuv.lockfile. - Critical: The
uv.lockfile pins exact versions of all dependencies (including transitive ones). It ensures that every developer and CI/CD pipeline uses the exact same environment, preventing "it works on my machine" issues. Commit this file to git.
- Run
4. Version Control (Git)
Set up a clean repository and ensure unwanted files are ignored.
- Initialize Git:
git initgit branch -M main
- Create
.gitignore:- Write a robust
.gitignoretailored for Python/MLOps. - Must Include:
- Environment:
.venv/,.env - Caches:
__pycache__/,.pytest_cache/,.ruff_cache/,.ty_cache/ - Builds:
dist/,build/,*.egg-info/ - Data/Models:
data/,models/,outputs/(unless using DVC/LFS) - MLflow local state:
mlflow.db,mlartifacts/,mlruns/ - IDE:
.vscode/(selectively),.idea/,.DS_Store
- Environment:
- Note: It is often good practice to commit project-specific
.vscode/settings.jsonbut ignoreUsersettings.
- Write a robust
- Verify Status:
git statusshould show only source files, config files, and the lockfile.
5. Task Runner & Project Instructions
Give every contributor — human or agent — one entrypoint and one written contract.
- Task Vocabulary: Create
mise.tomlwith the canonical tasksinstall,format,check,test,build, plusall=format->check->test->build.mise run allis the gate: git hooks and CI run that exact task and nothing else, so a green local run means a green pipeline. The mlops-automation skill details the tasks. - Pinned Toolchain: Declare non-Python tools in
[tools]and runmise lock, then commitmise.lock. Python dependencies are pinned byuv.lock; everything else is pinned bymise.lock. README.md(humans): what the project is, how to install it, how to run it.AGENTS.md(AI agents): the project overview, the exact commands, the definition of done, the conventions, and the repository layout. Keep it short and current — a staleAGENTS.mdmisleads every assistant that reads it.
6. IDE Configuration (VS Code)
Standardize the developer experience (DX) by committing project-specific settings.
- Install Recommended Extensions:
- Python Tier A:
ms-python.python,charliermarsh.ruff,astral-sh.ty,ms-toolsai.jupyter. - Productivity:
eamodio.gitlens,alefragnani.project-manager,usernamehw.errorlens. - One checker only: the project type-checks with
ty, so install Astral'sastral-sh.tyextension rather than Pylance. It ships the ty language server and setspython.languageServerto"None"itself, which prevents two checkers from reporting contradictory diagnostics on the same file.
- Python Tier A:
- Create
.vscodeDirectory:mkdir .vscode
- Create
settings.json:-
Configure settings to enforce code quality and use the
uvenvironment. -
Key Settings:
{ "[python]": { "editor.defaultFormatter": "charliermarsh.ruff", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.organizeImports": "explicit" } }, "python.defaultInterpreterPath": ".venv/bin/python", "python.terminal.activateEnvironment": true, "python.testing.pytestEnabled": true, "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true, "editor.rulers": [120], "files.exclude": { "**/__pycache__": true, "**/.pytest_cache": true, "**/.ruff_cache": true, "**/.ty_cache": true, "**/.venv": true } } -
Keep the ruler and the linter in agreement:
editor.rulersmust equal[tool.ruff] line-length(120 in this stack). A ruler at 88 against a 120-character limit makes the editor flag code thatruffaccepts, and developers reformat by hand to satisfy a line that no check enforces.
-
7. Verification & First Commit
Finalize the initialization.
- Verify Environment:
- Run
uv run python -c "import sys; print(sys.executable)"to confirm it uses the.venv.
- Run
- Verify the Gate:
- Run
mise run alland fix whatever it reports before the first commit.
- Run
- Initial Commit:
git add .git commit -m "chore: initialize project with uv, git, mise, and vscode settings"
8. Best Practices Summary
- One Command Setup: ideally,
mise run install(which wrapsuv sync) should be the only command needed to set up the environment. - One Command Gate:
mise run allis the single answer to "is this ready?" — locally, in hooks, and in CI. - Lockfiles: Commit both
uv.lock(Python) andmise.lock(tools) so all environments are identical. - Editor Config: Checked-in
.vscode/settings.jsonreduces onboarding friction and enforces standards (formatting, linting). - Dependency Separation: Keep production dependencies light; put testing/linting tools in
dev.
Self-Correction Checklist
- Lockfiles: Do
uv.lockandmise.lockexist and are they committed? - Virtual Env: Is
.venv/created and ignored in.gitignore? - Project Config: Does
pyproject.tomlvalidly describe the project, with an SPDXlicenseandlicense-files? - Git Cleanliness: Are secrets, large data files, and local MLflow state excluded?
- Instructions: Do
README.md(humans) andAGENTS.md(agents) exist and match the real commands? - Gate: Does
mise run allpass on a fresh clone? - Reproducibility: Can another developer
git cloneanduv syncto get the exact same state?
Signals
- GitHub stars
- 22
- Forks
- 4
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
mlops-initialization- Source
- github.com/mlops-courses/mlops-coding-skills