コンテンツにスキップ

Invoke Cheat Sheet

Overview

Invoke is a Python library for managing shell-oriented subprocesses and organizing executable tasks. It serves as both a command-line tool and a Python library, replacing Makefiles and shell scripts with clean Python functions. Invoke is the local-execution component that powers Fabric (which adds SSH capabilities).

Invoke provides task declaration via decorators, argument parsing from the command line, task dependencies, shell command execution with real-time output, and a flexible configuration system. It works on Python 3.6+ across all major operating systems.

Installation

pip install invoke

# Verify
inv --version
invoke --version

Core Usage

Basic tasks.py

from invoke import task

@task
def clean(c):
    """Remove build artifacts."""
    c.run("rm -rf build/ dist/ *.egg-info")
    c.run("find . -name '*.pyc' -delete")
    c.run("find . -name '__pycache__' -type d -exec rm -rf {} +")

@task
def test(c):
    """Run test suite."""
    c.run("pytest tests/ -v")

@task
def lint(c):
    """Run linters."""
    c.run("ruff check src/")
    c.run("mypy src/")

@task(pre=[clean, lint, test])
def build(c):
    """Build the package."""
    c.run("python -m build")

@task
def serve(c, port=8000):
    """Start development server."""
    c.run(f"python -m http.server {port}")
# Run tasks
inv clean
inv test
inv build
inv serve --port 9000

Core Commands

CommandDescription
inv --listList available tasks
inv <task>Run a task
inv <task> --helpShow task help
inv -e <task>Echo commands before running
inv -w <task>Warn on failure (don’t exit)
inv -d <task>Show detailed task info

Task Configuration

Arguments and Types

from invoke import task

@task
def deploy(c, env='staging', tag='latest', dry_run=False):
    """Deploy application.

    Args:
        env: Target environment (staging/production)
        tag: Docker image tag
        dry_run: Show commands without executing
    """
    cmd = f"docker pull myapp:{tag}"
    if dry_run:
        print(f"Would run: {cmd}")
    else:
        c.run(cmd)
        c.run(f"kubectl set image deployment/myapp myapp=myapp:{tag} -n {env}")

@task
def greet(c, name, greeting='Hello'):
    """Greet someone."""
    print(f"{greeting}, {name}!")

# Positional argument
@task(positional=['name'])
def hello(c, name):
    print(f"Hello {name}!")
inv deploy --env production --tag v2.0
inv deploy -e production -t v2.0
inv deploy --dry-run
inv greet --name World
inv hello Alice

Task Dependencies

from invoke import task

@task
def clean(c):
    c.run("rm -rf dist/")

@task
def compile(c):
    c.run("python -m compileall src/")

@task(pre=[clean, compile])
def build(c):
    """Build after cleaning and compiling."""
    c.run("python -m build")

@task(post=[clean])
def release(c):
    """Release, then clean up."""
    c.run("twine upload dist/*")

# Call tasks explicitly
@task
def deploy(c, env='staging'):
    build(c)  # Run build task first
    c.run(f"scp dist/*.whl {env}-server:/opt/app/")

Namespaces

# tasks/docker.py
from invoke import task

@task
def build(c, tag='latest'):
    c.run(f"docker build -t myapp:{tag} .")

@task
def push(c, tag='latest'):
    c.run(f"docker push myregistry/myapp:{tag}")

# tasks/__init__.py
from invoke import Collection
from tasks import docker, test as test_tasks

ns = Collection()
ns.add_collection(Collection.from_module(docker), name='docker')
ns.add_collection(Collection.from_module(test_tasks), name='test')
inv docker.build --tag v2.0
inv docker.push --tag v2.0
inv test.unit

Configuration

invoke.yaml

run:
  echo: true
  warn: false
  hide: false
  pty: false

tasks:
  search_root: .
  collection_name: tasks

my_project:
  deploy_host: web1.example.com
  db_host: db.example.com
  redis_host: redis.example.com
@task
def deploy(c):
    host = c.config.my_project.deploy_host
    c.run(f"ssh {host} 'cd /app && git pull'")

Environment-Based Config

# tasks.py
from invoke import task, Config

@task
def show_config(c):
    print(f"Deploy host: {c.config.deploy.host}")
    print(f"Deploy user: {c.config.deploy.user}")
# invoke.yaml
deploy:
  host: staging.example.com
  user: deploy

# invoke.production.yaml (override)
deploy:
  host: prod.example.com

Advanced Usage

Command Execution Options

@task
def advanced_run(c):
    # Capture output
    result = c.run("git rev-parse HEAD", hide=True)
    commit = result.stdout.strip()
    print(f"Current commit: {commit}")

    # Check success/failure
    result = c.run("test -f config.yaml", warn=True)
    if result.failed:
        print("Config not found, creating default...")
        c.run("cp config.example.yaml config.yaml")

    # Dry run pattern
    c.run("echo 'would deploy'", dry=True)

    # With environment variables
    c.run("echo $MY_VAR", env={"MY_VAR": "hello"})

    # Using pseudo-terminal
    c.run("python manage.py shell", pty=True)

    # Timeout
    c.run("long-running-command", timeout=60)

Watchers (Auto-Respond to Prompts)

from invoke import task, Responder

@task
def setup(c):
    yes_responder = Responder(
        pattern=r"Are you sure\?",
        response="yes\n",
    )
    c.run("dangerous-command", watchers=[yes_responder])

    sudo_responder = Responder(
        pattern=r"\[sudo\] password",
        response="mypassword\n",
    )
    c.run("sudo apt update", watchers=[sudo_responder])

Collection-Level Configuration

from invoke import task, Collection

@task
def build(c):
    c.run(f"docker build -t {c.config.image_name} .")

@task
def push(c):
    c.run(f"docker push {c.config.image_name}")

ns = Collection(build, push)
ns.configure({
    'image_name': 'myregistry/myapp:latest',
})

Error Handling

from invoke import task, UnexpectedExit

@task
def safe_deploy(c):
    try:
        c.run("pytest tests/")
    except UnexpectedExit as e:
        print(f"Tests failed with exit code {e.result.exited}")
        print("Aborting deployment")
        return

    c.run("docker build -t myapp .")
    c.run("docker push myapp")

Troubleshooting

IssueSolution
Task not foundCheck file is named tasks.py; verify @task decorator
Arguments not parsingUse --arg value format; check type hints
Command fails silentlyAdd echo=True to see commands; remove hide=True
Interactive command hangsUse pty=True for interactive commands
Config not loadingCheck invoke.yaml location and syntax
Import error in tasksEnsure all dependencies are installed
# List all tasks
inv --list

# Show task help
inv --help deploy

# Echo commands
inv -e deploy

# Debug configuration
inv --print-completion-script bash
python -c "from invoke import Config; print(Config().as_dict())"