Scripting uvx with package arguments

February 14, 2025 ยท View on GitHub

human (Feb 13, 2025, 11:19 PM)

uvx --with llm --with sqlite-utils ipython

Inspired by this write me a zsh script, then a bash script, then a zsh alias that all let me do this:

itry llm sqlite-utils datasette

Which turns that into

uvx --with llm --with sqlite-utils --python 3.13 ipython

assistant (Feb 13, 2025, 11:19 PM)

I'll help you create scripts and an alias for this functionality. The idea is to convert a space-separated list of packages into uvx arguments.

create Shell Scripts for uvx Package Management

# ZSH Script (itry.zsh)
#!/usr/bin/env zsh

# Convert space-separated packages into uvx format and launch ipython
function itry() {
    local packages=()
    local python_version="3.13"  # Default Python version
    
    # Process all arguments
    for arg in "$@"; do
        if [[ $arg == python=* ]]; then
            python_version="${arg#python=}"
        else
            packages+=("--with" "$arg")
        fi
    done
    
    # Execute uvx command with all packages
    uvx ${packages[@]} --python $python_version ipython
}

# Bash Script (itry.sh)
#!/usr/bin/env bash

# Convert space-separated packages into uvx format and launch ipython
function itry() {
    local packages=()
    local python_version="3.13"  # Default Python version
    
    # Process all arguments
    for arg in "$@"; do
        if [[ $arg == python=* ]]; then
            python_version="${arg#python=}"
        else
            packages+=("--with" "$arg")
        fi
    done
    
    # Execute uvx command with all packages
    uvx "${packages[@]}" --python "$python_version" ipython
}

# ZSH Alias (add to .zshrc)
alias itry='function _itry() { local args=(); for i in "$@"; do if [[ $i == python=* ]]; then pv="${i#python=}"; else args+=(--with $i); fi; done; uvx $args --python ${pv:-3.13} ipython }; _itry'

I've created three different implementations:

  1. A ZSH script that defines a function
  2. A Bash script that defines a similar function
  3. A ZSH alias that provides the same functionality in a single line

All three implementations:

  • Accept space-separated package names
  • Convert them into --with package format for uvx
  • Support an optional Python version specification (e.g., python=3.11)
  • Default to Python 3.13 if no version is specified
  • Launch ipython with the specified packages

To use these:

  1. For the ZSH script:
# Save as itry.zsh and source it
source itry.zsh
itry llm sqlite-utils datasette  # Basic usage
itry llm sqlite-utils python=3.11  # With custom Python version
  1. For the Bash script:
# Save as itry.sh and source it
source itry.sh
itry llm sqlite-utils datasette
  1. For the ZSH alias:
# Add the alias to your .zshrc
# Then use it like:
itry llm sqlite-utils datasette

Would you like me to explain any part of the implementation in more detail?

human (Feb 13, 2025, 11:19 PM)

is there a thing I can do for this that's likely to work across multiple shells?

assistant (Feb 13, 2025, 11:20 PM)

Yes! A standalone script would be the most portable solution across shells. Let's create an executable script that can work in any POSIX-compliant shell.

create Portable Shell Script for uvx Package Management

#!/bin/sh
# itry - A portable script for launching ipython with uvx packages
# Save this as 'itry' in your PATH (e.g., ~/bin/itry or /usr/local/bin/itry)

# Default Python version
PYTHON_VERSION="3.13"

# Help message
show_help() {
    cat << EOF
Usage: itry [packages...] [python=VERSION]
Launch ipython with specified packages using uvx.

Examples:
    itry llm sqlite-utils datasette
    itry llm sqlite-utils python=3.11
    itry --help

Options:
    --help      Show this help message
EOF
    exit 0
}

# Show help if requested
[ "\$1" = "--help" ] && show_help

# Initialize empty string for packages
PACKAGES=""

# Process all arguments
for arg in "$@"; do
    case "$arg" in
        python=*)
            PYTHON_VERSION="${arg#python=}"
            ;;
        *)
            PACKAGES="$PACKAGES --with $arg"
            ;;
    esac
done

# Remove leading space if present
PACKAGES="${PACKAGES# }"

# Execute uvx command
exec uvx $PACKAGES --python "$PYTHON_VERSION" ipython

This script:

  1. Uses #!/bin/sh for maximum portability
  2. Works in any POSIX-compliant shell (sh, bash, zsh, dash, etc.)
  3. Includes a help message (accessible via --help)
  4. Handles space-separated package names and Python version specification
  5. Uses exec to replace itself with the uvx process

To use it:

  1. Save it as itry (no extension) in your PATH (e.g., ~/bin/itry or /usr/local/bin/itry)
  2. Make it executable:
chmod +x ~/bin/itry

Then you can use it from any shell:

itry llm sqlite-utils datasette
itry llm sqlite-utils python=3.11
itry --help

This approach has several advantages:

  • Works across all POSIX shells without modification
  • No need to source anything or modify shell config files
  • Includes built-in help documentation
  • Easier to maintain as it's a single file
  • Can be version controlled and shared easily

The script is also more robust than the shell-specific versions since it:

  • Handles edge cases better
  • Provides help documentation
  • Uses more portable shell syntax
  • Avoids shell-specific features

Would you like me to explain any part of the implementation in more detail?

human (Feb 13, 2025, 11:20 PM)

drop the python=VERSION thing I always want to pass --python 3.13 to uvx under the hood

assistant (Feb 13, 2025, 11:20 PM)

Ah, that makes it even simpler! Here's a streamlined version:

create Simplified Portable Shell Script for uvx Package Management

#!/bin/sh
# itry - A portable script for launching ipython with uvx packages

# Show help if requested
[ "\$1" = "--help" ] && {
    echo "Usage: itry [packages...]"
    echo "Example: itry llm sqlite-utils datasette"
    exit 0
}

# Initialize empty string for packages
PACKAGES=""

# Process all arguments, adding --with before each
for arg in "$@"; do
    PACKAGES="$PACKAGES --with $arg"
done

# Remove leading space if present
PACKAGES="${PACKAGES# }"

# Execute uvx command with Python 3.13
exec uvx $PACKAGES --python 3.13 ipython

Much cleaner now! Save it as itry, make it executable with chmod +x itry, and put it in your PATH.

Usage is now just:

itry llm sqlite-utils datasette

This will always use Python 3.13 and you just list the packages you want. Simple and effective!