Wooey turns an argparse script into a web form and a queued job
A Django app that creates automatic web UIs for Python scripts.
At a glance
- What is it?
- Wooey is a Django app that reads a Python script's own argparse parser, renders it as a web form and runs each submission through Celery, aimed at colleagues who avoid the terminal. It fits a single analysis script well and stops there: dependency metadata that contradicts itself, and no documented answer for pipelines or permissions.
- Who is it for?
- Adopt Wooey when the work is one Python script whose arguments already parse, and skip it when the real requirement is a chained pipeline, a scheduler or per-user permissions, none of which appear anywhere in the written documentation.
- Can I use it commercially?
- Yes. BSD-3-Clause 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 2 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 October 23, 2026, and from our analysis. They are not legal advice.
Star history
- wooey/Wooey2,245 ★ · +0
| Repository | 2026-10-16 | 2026-10-23 |
|---|---|---|
| wooey/Wooey | 2.2k | 2.2k |
0 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
An argparse parser becomes the form schema
Wooey is a Django app that builds a web GUI and task interface for Python scripts that already parse their own arguments. That sentence comes from the project's own packaging description, and it sets the whole scope. The usual way to share an analysis script is to hand a colleague a terminal and a list of flags. Wooey inverts the arrangement: the script stays a script, the flags become form fields.
The payoff is aimed at the co-worker who has never opened a shell. Nothing about the workflow has to change, because the parser that documented the flags on the terminal is the parser Wooey reads to build the page. Rename an argument in argparse and the web form loses that field too, which cuts both ways: the interface cannot drift away from the documentation, but a private helper argument added for debugging will appear in the public form.
The unit of work is the script, not a tool definition file. Every consequence in this article follows from that one design choice.
Every submission becomes a Celery task, not a request
Wooey is not a synchronous form handler. Its dependency list opens with a queue and a web framework:
dependencies = [
"celery>=4,<6",
"clinto>=0.6.0",
"Django>=4.2,<6",
"django-autoslug",
"django-storages",
"eventlet>=0.22.1 ; platform_system == 'Windows'",
"filetype",
"packaging",
]Running one therefore needs a Celery broker and a worker process sitting beside the Django application, and that cost lands on whoever installs it rather than on the person clicking submit. `django-autoslug` gives each registered script a slug for its URL, `django-storages` carries uploaded inputs and kept results into a storage backend, and `filetype` handles type detection on files that pass through the queue.
Two of those pins are conditional, which tells you what the project expects to run on. `eventlet>=0.22.1` applies only on Windows, and `pypiwin32` joins it there on interpreters newer than 3.4. On Linux and macOS the eventlet marker never fires, so a Windows install and a Unix install are not the same dependency set.
The wooify console script bootstraps a script into the app
The package installs exactly one console entry point, and it is not named after a task:
[project.scripts]
wooify = "wooey.backend.command_line:bootstrap"Packaging also ships a raw script file from the repository root, recorded as `script-files = ["scripts/wooify"]`. The friendly command name points at an internal module path and a function called `bootstrap`, which is the ingestion story compressed into one line of metadata: a script goes in, and Wooey grows the wrapper that turns its parser into a task.
What that bootstrap writes is not described in the README. Readers are sent to the documentation at wooey.readthedocs.org for installation and other instructions, and to a demo-server at wooey.fly.dev for a test drive. The generated code is something you read in the docs or in the generated app itself, not from the README.
Two test runners and a coverage gate in one Makefile
The quickest way to see how the project is assembled is its Makefile, which builds an editable install with the development extras and then runs two different test runners:
testenv:
pip install -e .[dev]
test:
pytest --cov=wooey --cov-branch tests/*
python -m coverage run --append --branch --source=wooey -m django test --settings=wooey.test_settings wooey.testsBoth write into the same coverage data file, the second appending to the first, and the report step then carves out generated code:
python -m coverage report --omit='*migrations*','*wooey_scripts*','*tests/scripts*','*conf/*'That omit list is the useful part. Migrations, `wooey_scripts`, the fixture scripts under `tests/scripts` and `conf` are all excluded from the measured surface, so the app keeps generated script modules and per-instance configuration beside the code the maintainers count.
The development extras add pytest, pytest-cov, coverage, factory-boy < 3.0.0, mock, boto3, build, sphinx and watchdog[watchmedo]. Sphinx is there for a docs target that runs `cd docs && make html`. None of this is an end-user install path: the README gives no pip line for a running instance and points at wooey.readthedocs.org and the demo server instead.
The packaging metadata contradicts itself in two places
The first contradiction is the interpreter floor. `requires-python = ">=3.10.0"` blocks an install on anything older, yet the classifier list still advertises Python 3.7, 3.8, 3.9 and 3.10. One dependency marker is already dead under that floor: `importlib-metadata<5.0 ; python_version <= '3.7'` cannot be satisfied by any interpreter allowed to install the package. Plan from the classifiers and you would budget for a 3.9 deployment; read the floor and pip stops you.
The second contradiction is version drift. `pyproject.toml` declares 0.14.0, the newest tagged release is v0.13.2 from 2022-10-05, and the last push was on 2026-08-04, so the tip of the default branch sits ahead of anything published to an index. Earlier tags were v0.12.0 on 2020-04-16 and 0.11.0 on 2019-11-30, which puts the spacing between a tag and the branch it sits on in the same range as the rest of this repository's history.
Both contradictions share a cause: the packaging metadata is the only machine-readable statement of what Wooey needs, and it lags the code. Pair that with `celery>=4,<6` and `Django>=4.2,<6`, which cap both dependencies below their current major lines, and any deployment you build inherits a pinned, dated stack.
Galaxy is the only alternative named, and only thinly
The README positions Wooey against Galaxy, and against one specific thing: writing a tool description in a language-specific form. Galaxy expects each program to be described so the platform can build and run it, while Wooey starts from a script you already run and reads the arguments it already parses. For a small analysis script that duplicate description is the part you would rather not write, and the argument holds.
After that the documentation stops. There is no feature comparison with Galaxy, no migration note, and no statement about who should stay on which system. The aims Wooey sets out are documenting a workflow, letting colleagues run scripts, and the wrapping step itself. None of them is orchestration, and nothing in the repository root, which carries a `docker/` directory, a `docs/` tree, `scripts/`, `tests/` and the `wooey/` package, describes a scheduler, a dependency resolver between steps or a retry policy.
So keep the comparison narrow. For a one-shot script with a handful of flags, generating the form from argparse removes work a tool-definition workflow asks you to repeat. For a multi-step pipeline with pinned environments, nothing here claims the job.
Where the scope stops being one script
The usual reasons to reach for a job runner are absent from the written documentation. Wooey describes a form and a task, not a pipeline: no chaining between scripts, no scheduled runs, no priority for queued work. A batch that depends on those belongs in a different tool.
Permissions are the other gap. The documentation does not cover authentication, per-user isolation or who may register a script, so an instance opened beyond a trusted group needs answers before it goes online. Rollback is silent too: once a bootstrapped script has run and produced stored results, no documented procedure removes it or undoes the registration.
On licensing the position is plain. The code ships under BSD-3-Clause and the project classifiers repeat it as a BSD License, so wrapping Wooey inside internal tooling carries no copyleft condition on the code you write around it.
One check before you commit: open wooey.readthedocs.org and the demo at wooey.fly.dev, then confirm your script exposes its inputs through argparse. A script that reads positional arguments by hand gives the form nothing to render, and nothing in the project lets you declare fields yourself.
Editorial conclusion
Adopt Wooey when the work is one Python script whose arguments already parse, and skip it when the real requirement is a chained pipeline, a scheduler or per-user permissions, none of which appear anywhere in the written documentation. Verify three things first: that your script exposes its inputs through argparse, that you can run a Celery broker and worker beside the Django app, and that the version you install matches the 0.14.0 in pyproject.toml rather than the v0.13.2 tag. Open wooey.readthedocs.org and the demo at wooey.fly.dev before wiring anything into a group workflow.
Frequently asked questions
Does Wooey run my scripts on someone else's servers?
No. Wooey is a Django app you install into a project on infrastructure you control, and the project description calls it a web GUI and task interface for argparse scripts. The README points at your own documentation at wooey.readthedocs.org plus a demo-server at wooey.fly.dev, and nothing in the packaging metadata turns it into a hosted execution service.
What does Wooey need before a script will run in a browser?
A Django project, a Celery broker and a worker process, because the dependencies pin `celery>=4,<6` and `Django>=4.2,<6`. The task interface is queue-backed rather than a request handler, so a missing worker leaves the form rendered and nothing executed.
How do I get one of my scripts into Wooey?
The package installs a console script `wooify` mapped to `bootstrap` in `wooey.backend.command_line`, and ships a `scripts/wooify` file with it. The form fields are derived from what the script's own argparse parser exposes, and the README documents no way to declare fields by hand.
Can I run Wooey in Docker?
The repository root carries a `docker/` directory, and the README links a demo-server at wooey.fly.dev. No build or run command for that directory appears in the README, so take current instructions from wooey.readthedocs.org.
Is Wooey still being worked on?
The last push was on 2026-08-04, so the repository is not dormant. The gap is in packaging rather than commits: the newest tagged release is v0.13.2 from 2022-10-05 while pyproject.toml already declares 0.14.0, so an install from an index trails the default branch.
How does Wooey compare with Galaxy?
The README names Galaxy as the system Wooey avoids writing for, because Galaxy needs a language-specific tool description while Wooey wraps a program in simple python. No feature-by-feature comparison or migration path is given, so the documented difference stops at the wrapping step.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wooey-wooey)Star history chart for your README
[](https://hysenlabs.com/projects/wooey-wooey)Was this useful?