Claude Code for Python Fire: Auto CLI from Python Functions — Claude Skills 360 Blog
Blog / AI / Claude Code for Python Fire: Auto CLI from Python Functions
AI

Claude Code for Python Fire: Auto CLI from Python Functions

Published: March 30, 2028
Read time: 5 min read
By: Claude Skills 360

Python Fire turns any Python function, class, or module into a CLI with zero argument parsing code. pip install fire. Function: import fire; fire.Fire(fn) — positional args map to params, --name value for kwargs. Class: fire.Fire(MyClass) — methods become sub-commands; python app.py method --arg val. Multiple: fire.Fire({"deploy": deploy_fn, "rollback": rollback_fn}). fire.Fire(MyClass()) — instantiate then call methods. Named: fire.Fire(fn, name="mytool"). Trace: python app.py fn -- --trace — shows dispatch chain. Separator: python app.py fn other_fn -- --separator=,. Return: Fire prints return values — strings as-is, dicts/lists as JSON-like repr. Serializer: fire.core.Display for custom rendering. Nested class: class DB: def query(self): ...; class App: db = DB()python app.py db query. Help: python app.py --help, python app.py method --help — auto from docstrings. Type: Fire coerces "true"/"false" → bool, "1" → int, "[1,2]" → list. --flag → True, --noflag → False. Default args: Fire shows them in help. Variadic: def fn(*args, **kwargs) — passes positional and keyword freely. Pipe: echo "arg" | python app.py fn -. Input: - means stdin. fire.Fire works as a main() body. Claude Code generates python-fire CLIs, admin scripts, and multi-command tools from existing class APIs.

CLAUDE.md for Python Fire

## Python Fire Stack
- Version: fire >= 0.6 | pip install fire
- Function: fire.Fire(fn) — positional → args; --key value → kwargs
- Class: fire.Fire(MyClass) — methods become subcommands; instantiates automatically
- Dict: fire.Fire({"cmd1": fn1, "cmd2": fn2}) — explicit sub-command registry
- Nested: fire.Fire(App()) where App has attribute objects — chains as subcommands
- Types: "true"/"false" → bool; "1" → int; "[1,2]" → list; --flag/--noflag for bools
- Help: auto-generated from docstrings; python app.py -- --help for each level

Python Fire CLI Pipeline

# app/cli.py — Python Fire CLIs: functions, classes, nested commands, and multi-tool
from __future__ import annotations

import json
import os
import sys
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any

import fire


# ─────────────────────────────────────────────────────────────────────────────
# 1. Simple function CLI
# ─────────────────────────────────────────────────────────────────────────────

def greet(name: str, greeting: str = "Hello", *, count: int = 1, upper: bool = False) -> str:
    """
    Print a greeting.

    Args:
        name: Person to greet.
        greeting: Greeting word (default "Hello").
        count: How many times to repeat.
        upper: Convert to uppercase.

    Usage:
        python cli.py Alice
        python cli.py Alice --greeting Hi --count 3
        python cli.py Alice --upper
    """
    msg = f"{greeting}, {name}!"
    if upper:
        msg = msg.upper()
    for _ in range(count):
        print(msg)
    return msg


def add(*numbers: float) -> float:
    """Sum any number of arguments: python cli.py 1 2 3 4"""
    total = sum(numbers)
    print(f"Sum: {total}")
    return total


# ─────────────────────────────────────────────────────────────────────────────
# 2. Class-based CLI (each method = subcommand)
# ─────────────────────────────────────────────────────────────────────────────

class DeployTool:
    """
    Deployment CLI tool.

    Usage:
        python cli.py deploy --env staging
        python cli.py deploy status
        python cli.py deploy rollback --version v1.2.3
    """

    def __init__(self, env: str = "development", dry_run: bool = False):
        """
        Args:
            env: Target environment (development|staging|production).
            dry_run: Print actions without executing.
        """
        self.env = env
        self.dry_run = dry_run

    def deploy(self, version: str = "latest", services: str = "all") -> dict[str, Any]:
        """
        Deploy services to the environment.

        Args:
            version: Image tag to deploy.
            services: Comma-separated service list, or "all".
        """
        svc_list = services.split(",") if services != "all" else ["api", "worker", "scheduler"]
        result = {
            "env":      self.env,
            "version":  version,
            "services": svc_list,
            "dry_run":  self.dry_run,
        }
        if not self.dry_run:
            for svc in svc_list:
                print(f"  Deploying {svc} @ {version}{self.env}")
        else:
            print(f"  [dry-run] Would deploy: {result}")
        return result

    def rollback(self, version: str) -> None:
        """Roll back all services to a previous version."""
        if self.dry_run:
            print(f"  [dry-run] Would rollback to {version} in {self.env}")
        else:
            print(f"  Rolling back {self.env} to {version}")

    def status(self) -> dict[str, str]:
        """Show current deployment status."""
        status = {
            "env":     self.env,
            "api":     "running",
            "worker":  "running",
            "scheduler": "paused",
        }
        for k, v in status.items():
            indicator = "✔" if v == "running" else "⚠"
            print(f"  {indicator} {k}: {v}")
        return status

    def logs(self, service: str = "api", lines: int = 50) -> None:
        """Tail logs for a service."""
        print(f"  [Showing last {lines} lines of {service} in {self.env}]")
        # In real code: subprocess("kubectl logs ...", lines=lines)


# ─────────────────────────────────────────────────────────────────────────────
# 3. File operations CLI
# ─────────────────────────────────────────────────────────────────────────────

class FileTool:
    """
    File manipulation commands.

    python cli.py file count --path . --ext .py
    python cli.py file find --pattern "*.log"
    python cli.py file stats --path file.txt
    """

    def count(self, path: str = ".", ext: str = "") -> dict[str, int]:
        """Count files by extension."""
        root = Path(path)
        counts: dict[str, int] = {}
        for f in root.rglob("*"):
            if f.is_file():
                suffix = f.suffix or "(none)"
                counts[suffix] = counts.get(suffix, 0) + 1
        if ext:
            counts = {k: v for k, v in counts.items() if k == ext}
        for k, v in sorted(counts.items(), key=lambda x: -x[1])[:10]:
            print(f"  {k:<12} {v:>6}")
        return counts

    def find(self, pattern: str = "*.py", path: str = ".") -> list[str]:
        """Find files matching a glob pattern."""
        matches = sorted(str(f) for f in Path(path).rglob(pattern))
        for m in matches[:20]:
            print(f"  {m}")
        if len(matches) > 20:
            print(f"  ... and {len(matches)-20} more")
        return matches

    def stats(self, path: str) -> dict[str, Any]:
        """Show file stats: size, lines, last modified."""
        p = Path(path)
        if not p.exists():
            print(f"  Error: {path} not found")
            return {}
        stat = p.stat()
        lines = len(p.read_text(errors="replace").splitlines()) if p.is_file() else 0
        info = {
            "path":     str(p),
            "size":     stat.st_size,
            "lines":    lines,
            "modified": stat.st_mtime,
        }
        for k, v in info.items():
            print(f"  {k:<12} {v}")
        return info


# ─────────────────────────────────────────────────────────────────────────────
# 4. Nested commands (attribute-based)
# ─────────────────────────────────────────────────────────────────────────────

class DBCommands:
    """Database operations."""

    def migrate(self, target: str = "head") -> None:
        """Run database migrations."""
        print(f"  Running migrations → {target}")

    def seed(self, env: str = "development") -> None:
        """Seed the database with test data."""
        print(f"  Seeding {env} database")

    def reset(self, force: bool = False) -> None:
        """Drop and recreate the database (use --force to skip confirmation)."""
        if not force:
            confirm = input("  Reset database? [y/N] ").strip().lower()
            if confirm != "y":
                print("  Aborted")
                return
        print("  Resetting database...")


class ConfigCommands:
    """Configuration management."""

    def show(self, env: str = "development") -> None:
        """Print current configuration for an environment."""
        config = {"env": env, "debug": env == "development", "log_level": "INFO"}
        for k, v in config.items():
            print(f"  {k}: {v!r}")

    def validate(self, path: str = ".env") -> bool:
        """Validate a .env file for required keys."""
        required = ["DATABASE_URL", "SECRET_KEY", "REDIS_URL"]
        if not Path(path).exists():
            print(f"  File not found: {path}")
            return False
        content = Path(path).read_text()
        missing = [k for k in required if k not in content]
        if missing:
            print(f"  Missing keys: {missing}")
            return False
        print("  All required keys present ✔")
        return True


class App:
    """
    Multi-command application.

    python cli.py db migrate
    python cli.py db seed --env production
    python cli.py config show --env staging
    python cli.py config validate --path .env.prod
    """

    def __init__(self):
        self.db     = DBCommands()
        self.config = ConfigCommands()
        self.file   = FileTool()
        self.deploy = DeployTool()

    def version(self) -> str:
        """Print application version."""
        v = "1.0.0"
        print(f"  v{v}")
        return v

    def health(self) -> dict[str, str]:
        """Run a health check."""
        checks = {"database": "ok", "redis": "ok", "api": "ok"}
        for service, status in checks.items():
            indicator = "✔" if status == "ok" else "✗"
            print(f"  {indicator} {service}: {status}")
        return checks


# ─────────────────────────────────────────────────────────────────────────────
# 5. Dict-based multi-tool
# ─────────────────────────────────────────────────────────────────────────────

def build(tag: str = "latest", push: bool = False, platform: str = "linux/amd64") -> None:
    """Build a Docker image."""
    cmd = f"docker build -t myapp:{tag} --platform {platform} ."
    if push:
        cmd += f" && docker push myapp:{tag}"
    print(f"  {cmd}")


def test(path: str = ".", verbose: bool = False, coverage: bool = False) -> None:
    """Run the test suite."""
    cmd = "pytest " + path
    if verbose:
        cmd += " -v"
    if coverage:
        cmd += " --cov=app --cov-report=term-missing"
    print(f"  {cmd}")


def lint(path: str = ".", fix: bool = False) -> None:
    """Run linters."""
    for tool in ["ruff", "mypy"]:
        suffix = " --fix" if fix and tool == "ruff" else ""
        print(f"  {tool}{suffix} {path}")


COMMANDS = {
    "build":  build,
    "test":   test,
    "lint":   lint,
    "deploy": DeployTool,
    "app":    App,
}


# ─────────────────────────────────────────────────────────────────────────────
# Entry points
# ─────────────────────────────────────────────────────────────────────────────

def main_function():
    """fire.Fire on a single function."""
    fire.Fire(greet)


def main_class():
    """fire.Fire on a class."""
    fire.Fire(DeployTool)


def main_nested():
    """fire.Fire on a nested App instance."""
    fire.Fire(App)


def main_dict():
    """fire.Fire on a dict of commands."""
    fire.Fire(COMMANDS)


if __name__ == "__main__":
    # Default: expose the full App with nested sub-commands
    fire.Fire(App)

For the typer alternative — Typer provides type-annotated argument parsing with decorators (@app.command()), built-in help generation, and rich terminal output integration; Python Fire requires zero boilerplate to expose a function as a CLI (no decorators, no argument definitions), making it ideal for turning existing Python code into CLI scripts quickly, while Typer is better for production CLIs where you want fine-grained control over help text and argument validation. For the argparse alternative — argparse requires explicit add_argument() calls for each parameter; Python Fire reads function signatures, type annotations, default values, and docstrings automatically, eliminating 90% of the boilerplate for simple tools while still supporting complex nested sub-command hierarchies through class attributes. The Claude Skills 360 bundle includes Python Fire skill sets covering fire.Fire() on functions/classes/dicts, class method sub-commands, nested attribute commands, type coercion (bool/int/list), docstring help generation, DeployTool/FileTool/App class patterns, dict-based multi-command registry, variadic *args functions, —dry_run/—verbose boolean flags, and fire.Fire(App) nested application pattern. Start with the free tier to try auto-CLI code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free