Poe the Poet: a pyproject.toml task runner for Poetry and uv projects
A task runner that works well with poetry or uv.
At a glance
- What is it?
- Poe the Poet declares project tasks in pyproject.toml and runs them inside the Poetry or uv virtualenv, so you skip the poetry run prefix. It is worth adopting if your team already lives in pyproject.toml and your tasks are commands, scripts or small DAGs.
- Who is it for?
- Adopt Poe the Poet if your project already has a pyproject.toml and you want task definitions, argument declarations and virtualenv handling in one file rather than a Makefile plus wrapper scripts. Skip it if your build steps are not Python-centric or if your team cannot take a Poetry or uv dependency for the runtime environment.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 65 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Poe the Poet solves in a Poetry or uv project
A Python project with a pyproject.toml still tends to grow a second, informal interface: a Makefile, a shell script, or a README section listing the commands a contributor is expected to remember. Those commands almost always begin with poetry run or uv run, because the tools you want to invoke live in the project virtualenv rather than on the system path. The README describes Poe the Poet as a task runner that works well with poetry or uv, and the mechanism it uses to earn that description is simple: tasks declared under [tool.poe.tasks] are executed in the Poetry or uv virtualenv, so the run prefix disappears from the command line. The audience is the maintainer or team that already keeps configuration in pyproject.toml and would rather add a [tool.poe.tasks] table than maintain a parallel build script. It is a narrower audience than a general build tool, and the project is honest about that: the README also notes it works as a general purpose task runner, with tasks definable in a separate poe_tasks.toml.
How tasks are declared and executed
The declaration format is the core of the tool. A task can be a plain command string, or a table with a type suffix such as serve.script or tunnel.shell. The README's quick start shows all three forms in one block: test as a simple command, serve.script pointing at my_app.service:run(debug=True), and tunnel.shell holding a POSIX shell line. The task types listed in the feature set are commands, shell scripts, Python expressions and references to Python functions, so the type suffix selects the execution mechanism rather than just labelling the task. Named CLI arguments are declared in an args list, and the README example passes a default of ${AWS_REGION} for an argument exposed as --region or -r, which means an environment variable can be overridden per invocation without editing the file. Extra arguments given on the CLI are appended to the underlying command, which the quick start demonstrates with poe test -v tests/unit. Composition is the other half of the model: tasks can run in sequence, in parallel, or as a DAG, per the composition guide linked from the README. That is enough structure for a lint-test-build pipeline without a separate orchestration file.
Installation and the commands you actually run
There are two supported entry points. The first is a global install via pipx, which the README gives as pipx install poethepoet. The second is as a Poetry plugin, added to pyproject.toml as [tool.poetry.requires-plugins] with poethepoet = ">=0.48". The distinction matters for upgrades: a pipx install is versioned independently of the project, while the plugin route pins the task runner alongside the project's Poetry configuration. Once installed, the CLI surface is poe [options] task [task_args]. Running poe with no arguments lists the available tasks, because tasks are self documenting; the README notes that help messages and task grouping are optional additions to that output. Shell completion for task names and arguments is available and is documented under installation. Environment variables can be loaded from .env files, and tasks can reference environment variables even when no shell is involved. If you are not using Poetry, the README points to a guide for using poe without pyproject.toml, where tasks live in poe_tasks.toml instead.
Where the virtualenv assumption becomes a constraint
The design assumes a Python project with a Poetry or uv environment. If your build steps are mostly non-Python (a Rust extension, a frontend bundler, a container image build), the virtualenv handling that makes poe convenient buys you nothing, and you are adding a Python tool to run shell commands that a Makefile would run just as well. The README does state that tasks can run in another environment you specify, and that poe works as a general purpose task runner, so the constraint is soft rather than absolute. The harder question is version coupling. The README's plugin example pins poethepoet = ">=0.48", and the release history shows three releases in the two weeks before the last recorded push (v0.47.0, v0.47.1, v0.48.0). A fast release cadence is not a defect, but it does mean a floating constraint will pull in behaviour changes on a schedule you do not control. Pin the version in the plugin block or in your pipx install and read the release notes before moving. The README does not describe a stability policy, so I would treat that as unverified and check the repository's own documentation before relying on one.
Poe the Poet against Make and shell scripts
The obvious alternative is a Makefile. Make gives you target dependencies, and its DAG model is more general than what a task runner needs for most Python projects. The difference in approach is where the configuration lives and what the tool knows about your environment. Make knows nothing about Poetry or uv, so every recipe that needs a project dependency has to spell out poetry run or uv run, and every developer has to remember which. Poe the Poet reads the same pyproject.toml your package metadata already lives in, and resolves the virtualenv itself. The cost is that task definitions are Python-adjacent configuration rather than a language with decades of documentation and a large body of prior art. If a task needs conditional logic beyond what the args and composition features cover, a Makefile or a standalone script is the more direct tool. The README also mentions that poe can be used as a library to embed in other tools and that tasks can be defined in Python packages for reuse across projects, which is a capability a Makefile does not have.
Maintenance cost and what the MIT licence leaves open
The project is licensed MIT, which permits use, modification and redistribution with the licence text retained. That is permissive and imposes no copyleft obligation on your own code. It says nothing about the maintenance burden of the tool itself. On that front the material shows an active repository: the last push is recorded as 2026-07-12, the default branch is main, and the project is not archived. The feature list is broad enough that the surface area you depend on is a choice you make: a team using only command tasks has a much smaller upgrade surface than one using the DAG composition and library embedding features. The README does not document a deprecation policy for task syntax, so the practical mitigation is to keep task definitions simple and to check the changelog on each release. There is also an official Agent Skill for AI coding agents, which is a maintenance commitment on the project's side rather than yours, but it does signal that the tool is being positioned for agent-driven workflows as well as human ones.
Who should adopt it and what to verify first
Adopt it if your project already has a pyproject.toml, your team uses Poetry or uv, and your tasks are commands, scripts or small pipelines that currently live in a Makefile or a README. The migration is mechanical: move the command strings into [tool.poe.tasks], drop the poetry run prefix, and declare any frequently overridden values as named args. Do not adopt it if your build is dominated by non-Python tooling, or if you cannot accept a Poetry or uv dependency for the environment the tasks run in. Before you commit, verify three things against your own setup: that poe resolves the virtualenv for the exact Poetry or uv version you have installed, that the task types you need (cmd, shell, expr, script) behave as the documentation for your pinned version describes, and that your version constraint is pinned rather than floating, given the release cadence visible in the repository.
Editorial conclusion
Adopt Poe the Poet if your project already has a pyproject.toml and you want task definitions, argument declarations and virtualenv handling in one file rather than a Makefile plus wrapper scripts. Skip it if your build steps are not Python-centric or if your team cannot take a Poetry or uv dependency for the runtime environment. Before committing, install it with pipx, confirm that poe picks up the virtualenv for your specific Poetry or uv version, and check the [tool.poe.tasks] block against the task type documentation for the version you pin.
Community notes