Skip to main content

footman

A task runner with the soul of duty and the UX of typer: typed function signatures become real flags and positionals, modules become nested command groups, independent tasks run in parallel by default, and shell completion answers from a cached manifest in ~25 ms — without importing your code.

Ships two console scripts, footman and the two-letter fm. Zero runtime dependencies. Python 3.11+.

[!NOTE] Beta. footman is pre-1.0: the surface is settling, but minor versions may still include breaking changes — always called out in the changelog, never in a patch release. Pin the minor (footman~=0.29.0) if you build on it. The written stability promise lands with 1.0 — the road there is in ROADMAP.md.

Why

duty gets a lot right — the run() capture model, the decorator ergonomics — and footman keeps those ideas. Where it pushes is the parts that compound: completion served from a cache instead of re-importing your project on every TAB (~15× faster, measured), eager type and choice validation with errors that teach, a DAG scheduler that runs independent tasks concurrently (the same four-step check lands ~4× sooner than duty or invoke, measured) with true fail-fast that kills in-flight work on the first failure, runnable command groups and parameter forwarding that make composite commands like fm lint and check first-class, a monorepo task cascade that merges a tasks.py per folder, and a first-party story for testing your tasks. The receipts live in the comparison — every number reproducible from comparison/.

Taste

uv add --dev footman        # or: pip install footman
# tasks.py
from footman import task, group, run
from footman.tools import pytest, ruff

@task
def lint(fix: bool = False):
    "Run ruff over the project."
    ruff.check("src", fix=fix)

@task(pre=[lint])
def test(*pytest_args):
    "Run the test suite (extra args after --)."
    pytest(*pytest_args)

docs = group("docs", help="Documentation")

@docs.task(infinite=True)
def serve(port: int = 8000):
    "Serve the docs locally."
    run(f"mkdocs serve -a localhost:{port}")
$ fm lint --fix
$ fm lint test docs.serve --port=8001   # one chain; independent tasks run in parallel
$ fm test -- -k grammar -x              # everything after -- goes to pytest
$ fm deploy produ
fm: deploy: <target> must be one of dev|staging|prod (got 'produ') — did you mean 'prod'?
$ fm --install-completion               # detects your shell; TAB answers in ~25 ms

One file, dependencies included

A tasks file can declare what it needs inline (PEP 723), and then it needs no project at all — drop it in any folder and run it:

#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["footman", "httpx"]
# ///
import footman
from footman import task

@task
def health(url: str = "https://example.com"):
    "Check a deployment is up."
    import httpx
    print(httpx.get(url).status_code)

if __name__ == "__main__":
    footman.main(__file__)

fm health builds that environment once and runs inside it; chmod +x and ./deploy.py health works with no runner installed at all. Checked into a project that pins footman, the header is simply ignored and the file runs on the project's dependencies — portable and at home.

Learn more

Documentation — start with Getting started, then the good parts: typed signatures · chaining & parallelism · monorepos · composing tasks · running tools · testing your tasks · completion · CI & automation · comparison with duty / invoke / poe / typer

MIT licensed. The road to 1.0 lives in ROADMAP.md.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

footman-0.29.1.tar.gz (503.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

footman-0.29.1-py3-none-any.whl (548.7 kB view details)

Uploaded Python 3

File details

Details for the file footman-0.29.1.tar.gz.

File metadata

  • Download URL: footman-0.29.1.tar.gz
  • Upload date:
  • Size: 503.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for footman-0.29.1.tar.gz
Algorithm Hash digest
SHA256 94c632e6e361321a03966a35a5900589ce039d1bb8a5f3a52c57922a6283089c
MD5 1d58d8dc01a49513672c16f6a523820f
BLAKE2b-256 9ce83b88c8f583b2f96db6c8766822629d6865f74b7a86c0ace9dce0d13ddf3b

See more details on using hashes here.

Provenance

The following attestation bundles were made for footman-0.29.1.tar.gz:

Publisher: release.yml on willemkokke/footman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file footman-0.29.1-py3-none-any.whl.

File metadata

  • Download URL: footman-0.29.1-py3-none-any.whl
  • Upload date:
  • Size: 548.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for footman-0.29.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f69b5dbf199efc2d86c4b83717e7c80b710eeb2bd24b77f4a973265816f3e974
MD5 121fcf1280852a42fcb7d6768a84cc23
BLAKE2b-256 415ab2605bf6d712aa71a849b41b18ccb4f0b26184a85db51c7de9d109de5b97

See more details on using hashes here.

Provenance

The following attestation bundles were made for footman-0.29.1-py3-none-any.whl:

Publisher: release.yml on willemkokke/footman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.50.0

2 files

0.49.1

2 files

0.49.0

2 files

0.48.0

2 files

0.47.0

2 files

0.46.0

2 files

0.45.0

2 files

0.44.0

2 files

0.43.0

2 files

0.42.0

2 files

0.41.0

2 files

0.40.0

2 files

0.39.1

2 files

0.39.0

2 files

0.38.1

2 files

0.38.0

2 files

0.37.0

2 files

0.36.0

2 files

0.35.0

2 files

0.34.0

2 files

0.33.0

2 files

0.32.0

2 files

0.31.0

2 files

0.30.0

2 files

This release

0.29.1 This release

2 files

0.29.0

2 files

0.28.1

2 files

0.28.0

2 files

0.27.1

2 files

0.27.0

2 files

0.26.0

2 files

0.25.0

2 files

0.24.0

2 files

0.23.0

2 files

0.22.0

2 files

0.21.0

2 files

0.20.0

2 files

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

0.16.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.0

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

0.0.2

2 files

0.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page