Skip to content
/ rav Public

Python + YAML to shortcut various CLI commands. Sort of like `npm run <your script here>` but without all the package manager stuff.

Notifications You must be signed in to change notification settings

jmitchel3/rav

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

34 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

rav

A cross-platform Python CLI to shortcut to command-line commands with powerful file download capabilities and integrity verification. Inspired by Makefiles and npm scripts.

Features

✨ Script Management: Define and run custom command shortcuts πŸ”— Command Groups: Share working_dir and prefix across related commands πŸ“¦ File Downloads: Download files with integrity verification πŸ”’ Security: Subresource Integrity (SRI) hash verification 🎨 Rich Output: Beautiful terminal output with progress indicators ⚑ Multiple Formats: Support for single commands and multi-command sequences πŸ”§ Flexible Config: Use rav, scripts, or commands as top-level keys πŸ”€ Variables: Define reusable values with ${{ vars.NAME }} syntax

Table of Contents

Install

It's recommended that you use a virtual environment with rav.

python3 -m pip install rav

Minimum python version is 3.9

Quick Start

Option 1: Interactive Setup

cd ~/path/to/project
rav new

Run through the setup wizard to create rav.yaml

Option 2: Manual Setup

Create rav.yaml:

scripts:
    echo: echo hello world
    server: python -m http.server 8000

Run commands:

rav run echo     # or rav x echo
rav run server   # Start development server  
rav list         # Show all available commands

CLI Commands Reference

Core Commands

Command Description Example
rav run <command> Execute a script command rav run server
rav x <command> Shortcut for rav run rav x echo
rav list List all available commands rav list
rav new Create new rav project with wizard rav new
rav sample Generate sample rav.yaml file rav sample
rav version Show rav version rav version

Download Commands

Command Description Example
rav download <config> Download files using config rav download staticfiles
rav downloads <config> Alias for rav download rav downloads staticfiles

Command Options

Option Description Example
-f, --file Use custom rav file rav run -f custom.yaml echo
--overwrite Force overwrite existing files rav sample --overwrite
--verbose Enable verbose output rav --verbose run command

Quick Examples

Script execution:

rav x server          # Start development server
rav x test            # Run tests  
rav x build           # Build project

Custom files:

rav run -f project.yaml deploy
rav list -f staging.yaml

Project management:

rav new              # Interactive project setup
rav sample           # Create example file
rav list             # View available commands

Script Configuration

The configuration block is flexible. Use rav, scripts, or commands as the top-level key.

rav.yaml

name: web-development-toolkit

scripts:
    # Development servers
    dev: python -m http.server 8000
    dev-secure: python -m http.server 8443 --bind 127.0.0.1
    
    # Testing and quality assurance  
    test: pytest tests/ -v
    lint: flake8 src/ tests/
    format: black src/ tests/
    
    # Build and deployment
    build:
        - npm run build
        - python setup.py sdist bdist_wheel
        - echo "Build complete!"
    
    deploy:
        - rav run test
        - rav run build  
        - rsync -av dist/ user@server:/var/www/

downloads:
    frontend-deps:
        destination: static/vendor
        overwrite: true
        files:
            - name: htmx.min.js
              url: https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
              integrity: sha384-Akqfrbj/HpNVo8k11SXBb6TlBWmXXlYQrCSqEWmyKJe+hDm3Z/B2WVG4smwBkRVm
            - name: tailwind.css
              url: https://cdn.tailwindcss.com/3.4.0/tailwind.min.css

Flexible Configuration Keys

The following all work and will run in this exact order (rav first, scripts second, commands last):

rav:
    echo: echo "this is awesome"
    server: venv/bin/python -m http.server
scripts:
    echo: echo "this is awesome"  
    server: venv/bin/python -m http.server
commands:
    echo: echo "this is awesome"
    server: venv/bin/python -m http.server

Basic Syntax

Commands follow this simple pattern:

rav run <command>       # Execute a script command
rav x <command>         # Shortcut for rav run
rav list                # Show all available commands

Sample Project

Generate a sample project to explore features:

rav sample              # Creates rav.sample.yaml
rav run -f rav.sample.yaml echo

Custom Rav File

Rav supports custom yaml files by default. The yaml declaration needs to be any of the following:

  • rav
  • scripts
  • commands

project.yaml

rav:
    sweet: echo "this is working"
    echo: echo "so is this"

rav.basic.yaml

scripts:
    sweet: echo "this is working"
    echo: echo "so is this"
rav run -f project.yaml sweet

or

rav run --file rav.other.yaml echo

Here's a few rules for custom files:

  • -f or --file is used to specify a custom rav file
  • -f or --file must be used prior to the command shortcut name (e.g. rav run -f <your-new-file> <your-command>)

Multiple Commands at Once

rav.yaml

scripts:
    multi: 
        - echo this is
        - echo awesome
        - echo simple
        - echo and 
        - echo easy

Run with:

rav run multi

This is the same as running:

echo this is && echo awesome && echo simple && echo and && echo easy

Variables

Define reusable values with ${{ vars.NAME }} syntax. Great for templates and boilerplates where configuration varies between projects.

Basic Usage

vars:
  PROJECT_NAME: myproject
  PORT: "8000"

scripts:
  server: uv run uvicorn ${{ vars.PROJECT_NAME }}.asgi:application --port ${{ vars.PORT }}
  migrate: uv run python manage.py migrate
  echo: echo "Running ${{ vars.PROJECT_NAME }}"

Run with:

rav run server
# Executes: uv run uvicorn myproject.asgi:application --port 8000

Configuration Keys

Both vars and variables work as the top-level key:

vars:
  PROJECT_NAME: myproject
variables:
  PROJECT_NAME: myproject

Environment Variable Fallback

Variables fall back to environment variables if not defined in YAML:

scripts:
  whoami: echo "Home is ${{ vars.HOME }}"  # Uses $HOME from environment
  greet: echo "Hello ${{ vars.USER }}"     # Uses $USER from environment

Variables with Command Groups

Variables work seamlessly with command groups:

vars:
  PROJECT_NAME: myproject
  PYTHON: uv run python

scripts:
  backend:
    working_dir: backend/src
    prefix: ${{ vars.PYTHON }}

  backend:server: manage.py runserver
  backend:migrate: manage.py migrate

View Resolved Variables

Use rav list --expanded to see commands with variables resolved:

rav list --expanded
┏━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Command ┃ Script                                               ┃
┑━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
β”‚ server  β”‚ uv run uvicorn myproject.asgi:application --port 8000β”‚
β”‚ echo    β”‚ echo "Running myproject"                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Command Groups

Command groups allow you to define shared working_dir and prefix settings that are inherited by related commands. This is useful when you have multiple commands that share common configuration.

Basic Group Syntax

Define a group using a name ending with : pattern. Commands prefixed with that group name inherit its settings:

scripts:
    # Group definition
    backend:
        working_dir: backend/src
        prefix: "uv run"
        cmd: uvicorn app:application --reload

    # These inherit working_dir and prefix from backend:
    backend:migrate: python manage.py migrate
    backend:shell: python manage.py shell
    backend:test: pytest

Running rav run backend:migrate executes:

cd backend/src && uv run python manage.py migrate

Group Configuration Options

Option Description
working_dir Directory to cd into before running commands
prefix String prepended to each command
cmd Default command when running the group itself

Overriding Group Settings

Individual commands can override their group's settings:

scripts:
    backend:
        working_dir: backend/src
        prefix: "uv run"
        cmd: uvicorn app:application --reload

    # Inherits both working_dir and prefix
    backend:migrate: python manage.py migrate

    # Override just the prefix (empty = no prefix)
    backend:install:
        prefix:
        cmd: uv sync --dev

    # Override both working_dir and prefix
    backend:docs:
        working_dir: backend/docs
        prefix: "mkdocs"
        cmd: serve

Real-World Example: Django with Doppler and UV

Using command groups with secret injection and Python environment management:

scripts:
    # Backend group with uv runner
    backend:
        working_dir: backend/src
        prefix: "uv run python manage.py"

    backend:migrate: migrate
    backend:makemigrations: makemigrations
    backend:createsuperuser: createsuperuser
    backend:shell: shell
    backend:collectstatic: collectstatic --noinput

    # Production with secrets injection
    prod:
        working_dir: backend/src
        prefix: "doppler run -- uv run python manage.py"

    prod:migrate: migrate
    prod:collectstatic: collectstatic --noinput

    # Frontend group
    frontend:
        working_dir: frontend
        prefix: "npm run"

    frontend:dev: dev
    frontend:build: build
    frontend:test: test

Usage:

rav run backend:migrate           # β†’ cd backend/src && uv run python manage.py migrate
rav run prod:migrate              # β†’ cd backend/src && doppler run -- uv run python manage.py migrate
rav run frontend:build            # β†’ cd frontend && npm run build

Multi-Command Groups

Groups work with multi-command lists too:

scripts:
    backend:
        working_dir: backend/src
        prefix: "uv run"

    backend:setup:
        - echo "Setting up database..."
        - python manage.py migrate
        - python manage.py collectstatic --noinput
        - echo "Setup complete!"

Each command in the list gets the prefix applied:

cd backend/src && uv run echo "Setting up database..." && uv run python manage.py migrate && ...

Passing Arguments

Arguments are appended to the last command:

rav run backend:migrate myapp
# β†’ cd backend/src && uv run python manage.py migrate myapp

Expanded List View

Use --expanded to see fully resolved commands:

rav list --expanded

File Downloads

Rav includes powerful file download capabilities with support for integrity verification, custom destinations, and batch downloads.

Basic Download Configuration

Add a downloads section to your rav.yaml:

name: my-project

scripts:
    serve: python -m http.server

downloads:
    assets:
        destination: static/vendor
        files:
            - name: htmx.min.js
              url: https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
            - name: tailwind.css
              url: https://cdn.tailwindcss.com/3.4.0/tailwind.min.css

Download Commands

rav download assets     # Download all files in 'assets' config
rav downloads assets    # Same as above (alias)

Advanced Download Configuration

downloads:
    frontend-deps:
        name: Frontend Dependencies
        destination: static/vendor
        verbose: true                    # Show detailed progress
        overwrite: true                  # Overwrite existing files
        raise_on_error: false           # Continue on individual file errors
        files:
            - name: htmx.min.js
              url: https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
              integrity: sha384-Akqfrbj/HpNVo8k11SXBb6TlBWmXXlYQrCSqEWmyKJe+hDm3Z/B2WVG4smwBkRVm
              destination: static/js     # Override global destination
              overwrite: false           # Override global overwrite setting
            
            - name: bootstrap.min.css
              url: https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css
              destination: static/css

Configuration Options

Option Level Description Default
name Download Human-readable name for the download set -
destination Download/File Where to save files Required
verbose Download Show detailed download progress true
overwrite Download/File Overwrite existing files false
raise_on_error Download Stop on any download error false
integrity File SRI hash for verification -
url File Download URL Required
name or filename File Local filename URL basename

File-Level Overrides

Individual files can override the download-level settings:

downloads:
    mixed-settings:
        destination: assets/
        overwrite: false
        verbose: true
        files:
            - name: important-file.js
              url: https://example.com/file.js
              overwrite: true          # Override: will overwrite
              destination: critical/   # Override: different folder
            
            - name: optional-file.css
              url: https://example.com/style.css
              # Uses download-level settings

Download Output

Rav provides rich, colored output showing download progress:

πŸ“₯ Starting download: frontend-deps
Destination: static/vendor
Files to download: 3
Overwrite existing: true

[1/3] ⬇️  Downloading: htmx.min.js
   β†’ From: https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
   β†’ Integrity: sha384-Akqfrbj/...
   βœ… Integrity verified (sha384)
   βœ… Success! (45,234 bytes)

[2/3] ⏭️  Skipping existing file: bootstrap.min.css

[3/3] ⬇️  Downloading: alpine.min.js
   βœ… Success! (15,678 bytes)

---------------------------------------
πŸ“Š Download Summary:
   βœ… Downloaded: 2 files
   ⏭️  Skipped: 1 files
---------------------------------------

Integrity Verification

Rav supports Subresource Integrity (SRI) verification to ensure downloaded files haven't been tampered with.

What is SRI?

Subresource Integrity is a security feature that allows you to verify that downloaded files haven't been modified. It uses cryptographic hashes (SHA256, SHA384, SHA512) to ensure file integrity.

Supported Hash Algorithms

  • SHA256: sha256-<base64hash>
  • SHA384: sha384-<base64hash>
  • SHA512: sha512-<base64hash>

Getting SRI Hashes

You can generate SRI hashes using online tools or command line:

Online Tools:

Command Line:

# SHA384 (recommended)
curl -s https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js | \
  openssl dgst -sha384 -binary | openssl base64 -A

# SHA256
curl -s https://example.com/file.js | \
  openssl dgst -sha256 -binary | openssl base64 -A

Using Integrity Verification

Add the integrity field to any file in your download configuration:

downloads:
    secure-assets:
        destination: static/vendor
        files:
            - name: htmx.min.js
              url: https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
              integrity: sha384-Akqfrbj/HpNVo8k11SXBb6TlBWmXXlYQrCSqEWmyKJe+hDm3Z/B2WVG4smwBkRVm
            
            - name: bootstrap.min.css
              url: https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css
              integrity: sha384-9ndCyUa/9zzCGWL/iDMdwc9/z3dNS0MaTp5XhVpw5gGa6NZJK5YF6vZmN3K5J5zF

Integrity Verification Process

When integrity is specified, rav will:

  1. Download the file to a temporary location
  2. Calculate the file's hash using the specified algorithm
  3. Compare against the expected hash
  4. Move file to final destination only if verification passes
  5. Delete file and report error if verification fails

Error Handling

With raise_on_error: false (default):

  • Failed verification logs an error and continues
  • Failed files are not saved to destination
  • Download summary shows verification failures

With raise_on_error: true:

  • Failed verification stops the entire download process
  • Throws an exception with detailed error information

Example Output with Integrity

[1/2] ⬇️  Downloading: htmx.min.js
   β†’ From: https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
   β†’ Integrity: sha384-Akqfrbj/...
   β†’ Downloading to temp for verification: /tmp/rav_downloads/htmx.min.js
   βœ… Integrity verified (sha384)
   β†’ Downloaded to final destination: static/vendor/htmx.min.js
   βœ… Success! (45,234 bytes)

[2/2] ⬇️  Downloading: compromised-file.js
   β†’ From: https://example.com/file.js
   β†’ Integrity: sha384-Expected123...
   ❌ Integrity check failed: sha384-Actual456... != sha384-Expected123...

Security Best Practices

  1. Always use integrity hashes for CDN files
  2. Use SHA384 or SHA512 for better security than SHA256
  3. Verify hashes from trusted sources (official documentation, package registries)
  4. Set raise_on_error: true for critical security files
  5. Keep hashes updated when updating file versions

Complete Examples

Web Development Project

A complete rav.yaml for a modern web development workflow:

name: my-web-app

scripts:
    # Development
    dev: python -m http.server 8000
    dev-watch: 
        - npm run watch
        - rav run dev
    
    # Code quality
    lint:
        - flake8 src/
        - npm run lint
        - echo "βœ… Linting complete"
    
    format:
        - black src/
        - prettier --write static/js/
    
    test:
        - pytest tests/ -v --cov=src
        - npm test
    
    # Build pipeline
    build:
        - rm -rf dist/
        - rav download frontend-deps
        - npm run build
        - python setup.py sdist bdist_wheel
        - echo "πŸš€ Build complete!"
    
    # Deployment
    deploy-staging:
        - rav run test
        - rav run build
        - rsync -av dist/ staging@server:/var/www/staging/
    
    deploy-prod:
        - rav run test
        - rav run build
        - rsync -av dist/ prod@server:/var/www/production/

downloads:
    frontend-deps:
        name: Frontend Dependencies
        destination: static/vendor
        verbose: true
        overwrite: true
        files:
            # CSS Frameworks
            - name: bootstrap.min.css
              url: https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css
              integrity: sha384-9ndCyUa/9zzCGWL/iDMdwc9/z3dNS0MaTp5XhVpw5gGa6NZJK5YF6vZmN3K5J5zF
              destination: static/css
            
            # JavaScript Libraries
            - name: htmx.min.js
              url: https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js
              integrity: sha384-Akqfrbj/HpNVo8k11SXBb6TlBWmXXlYQrCSqEWmyKJe+hDm3Z/B2WVG4smwBkRVm
              destination: static/js
            
            - name: alpine.min.js
              url: https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js
              destination: static/js

Data Science Project

Perfect for Jupyter notebooks and data analysis:

name: data-analysis-project

scripts:
    # Environment management
    setup:
        - python -m venv venv
        - venv/bin/pip install -r requirements.txt
        - echo "βœ… Environment ready!"
    
    # Jupyter workflows
    notebook: venv/bin/jupyter lab --port=8888
    notebook-clean: venv/bin/jupyter nbconvert --clear-output notebooks/*.ipynb
    
    # Data processing
    download-data: python scripts/download_datasets.py
    process: 
        - python scripts/clean_data.py
        - python scripts/feature_engineering.py
        - echo "πŸ“Š Data processing complete"
    
    # Analysis and reporting
    analyze: venv/bin/python scripts/analyze.py
    report: 
        - venv/bin/jupyter nbconvert --to html notebooks/analysis.ipynb
        - echo "πŸ“‘ Report generated: notebooks/analysis.html"
    
    # Model training
    train:
        - rav run process
        - python scripts/train_model.py
        - echo "πŸ€– Model training complete"

downloads:
    datasets:
        destination: data/raw
        files:
            - name: sample_data.csv
              url: https://example.com/datasets/sample.csv
            - name: reference_data.json
              url: https://api.example.com/reference/data.json

DevOps/Infrastructure Project

For managing deployments and infrastructure:

name: infrastructure-toolkit

scripts:
    # Infrastructure
    plan: terraform plan
    apply: terraform apply -auto-approve
    destroy: terraform destroy -auto-approve
    
    # Docker workflows
    build: docker build -t myapp:latest .
    run: docker run -p 8080:8080 myapp:latest
    push: 
        - docker tag myapp:latest registry.com/myapp:latest
        - docker push registry.com/myapp:latest
    
    # Kubernetes
    deploy:
        - kubectl apply -f k8s/
        - kubectl rollout status deployment/myapp
    
    logs: kubectl logs -f deployment/myapp
    status: kubectl get pods,services,deployments
    
    # Monitoring setup
    setup-monitoring:
        - rav download monitoring-stack
        - kubectl apply -f monitoring/
        - echo "πŸ“Š Monitoring stack deployed"

downloads:
    monitoring-stack:
        destination: monitoring
        files:
            - name: prometheus.yaml
              url: https://raw.githubusercontent.com/prometheus/prometheus/main/documentation/examples/prometheus.yml
            - name: grafana-dashboard.json
              url: https://grafana.com/api/dashboards/1860/revisions/latest/download

Tips and Best Practices

Script Organization

  • Group related commands using descriptive names
  • Use comments in YAML to document complex workflows
  • Chain commands with rav run for reusable components
  • Keep scripts simple - complex logic belongs in separate files

File Downloads

  • Always use integrity hashes for security
  • Organize by purpose (frontend-deps, datasets, configs)
  • Use descriptive destination paths for better organization
  • Set appropriate overwrite policies per use case

Project Structure

my-project/
β”œβ”€β”€ rav.yaml              # Main configuration
β”œβ”€β”€ rav.dev.yaml          # Development-specific config
β”œβ”€β”€ rav.prod.yaml         # Production-specific config
β”œβ”€β”€ scripts/              # Complex automation scripts
β”œβ”€β”€ static/vendor/        # Downloaded dependencies
└── data/raw/            # Downloaded datasets

Cross-Platform Compatibility

scripts:
    # Universal commands (recommended)
    test: python -m pytest tests/
    serve: python -m http.server 8000
    
    # Platform-specific alternatives
    serve-win: python -m http.server 8000
    serve-unix: python3 -m http.server 8000

About

Python + YAML to shortcut various CLI commands. Sort of like `npm run <your script here>` but without all the package manager stuff.

Resources

Stars

Watchers

Forks

Contributors 4

  •  
  •  
  •  
  •  

Languages