uvmk: A Global CLI to Scaffold uv Python Projects (Mac, Linux, Windows)

· Travis Rodgers  · 3 min read

If you spin up Python projects often, you know the routine:

  • create a folder
  • uv init
  • create a venv
  • activate it
  • create main.py
  • repeat

I wanted a single global command to scaffold a clean uv Python project from any directory, landing inside the project with an activated venv, ready to work.

That’s what uvmk is.

What is uvmk?

uvmk is a small, installable CLI that:

  • runs uv init <projectname>
  • runs uv venv
  • activates the virtual environment
  • creates a starter main.py

It’s intentionally minimal. No frameworks. No opinions about linting. Just the baseline you do every time anyway.

Then, on top of that CLI, you add a shell helper so the experience feels like “one touch”:

  • macOS/Linux (zsh): mkpy myproject creates, cds in, and activates the venv
  • Windows (PowerShell): same idea in your PowerShell profile

Benefits

1) Faster startup with fewer mistakes

When setup is repeatable, you don’t forget steps (venv, starter file, etc.).

2) Works across Mac, Linux, and Windows

The CLI does the same thing anywhere you can run uv, and the shell helper handles the “cd + activate” experience per platform.

3) Clean “ready to go” workflow

A CLI can’t change your current shell session, but a shell function can—so you land in a ready state without thinking about it.

4) Built on uv tools

uv tool install is a clean way to install a tiny utility globally so it’s available on your PATH.


Install: uvmk (global command)

Clone the uvmk repo.

From the root of the uvmk repo:

uv tool install .

If uv warns that the tool bin directory isn’t on your PATH:

uv tool update-shell

Restart your terminal, then verify:

which uvmk
uvmk --help

macOS / Linux (zsh): add the mkpy helper

Add this function to your ~/.zshrc:

mkpy() {
  local name="$1"
  [[ -z "$name" ]] && { echo "Usage: mkpy <projectname>"; return 2; }

  # Capture ALL output; only print it if uvmk fails.
  local out
  out="$(uvmk "$name" 2>&1)" || { echo "$out"; return 1; }

  cd "$name" || return $?
  source ".venv/bin/activate" || return $?

  echo "$name activated and ready"
}

Reload your shell:

source ~/.zshrc

Use it:

mkpy yourproject

Windows (PowerShell): add the mkpy helper

1) Open your PowerShell profile

notepad $PROFILE

If it says the file doesn’t exist, create it:

New-Item -ItemType File -Path $PROFILE -Force
notepad $PROFILE

2) Add the mkpy function

Paste this into your profile:

function mkpy {
  param(
    [Parameter(Mandatory = $true)]
    [string]$Name
  )

  # Capture ALL output; only print it if uvmk fails.
  $out = & uvmk $Name 2>&1
  if ($LASTEXITCODE -ne 0) {
    $out | Write-Host
    return
  }

  Set-Location $Name
  .\.venv\Scripts\Activate.ps1

  Write-Host "$Name activated and ready"
}

3) Reload your profile

. $PROFILE

4) Use it

mkpy yourproject

If activation is blocked

If you see an execution policy error when activating, run this once:

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

(Or just for the current session:)

Set-ExecutionPolicy -Scope Process Bypass

What uvmk generates

A new project folder like:

myproject/
  .venv/
  main.py
  pyproject.toml

Nothing fancy—just enough to be productive instantly.


Updating after changes

If you pull updates to this repo and want to reinstall the CLI:

uv tool uninstall uvmk
uv tool install .
rehash

Closing

If you build lots of small tools, experiments, scripts, or prototypes, saving a minute per project adds up quickly.

uvmk is intentionally tiny: a global command to create a clean uv Python project anywhere, plus small shell helpers to drop you into an activated environment instantly.

This page may contain affiliate links. Please see my affiliate disclaimer for more info.

Related Posts

View All Posts »