CLI¶
The odf command-line tool scaffolds new projects and runs existing ones. It is
installed with the package; the ui extra adds the UI odf run starts by default:
$ odf --help
Usage: odf [OPTIONS] COMMAND [ARGS]...
Open Data Framework CLI.
Commands:
init Scaffold a new ODF project: a config.toml and an importable app package.
run Start a project: import its app package, load its config, and run until Ctrl+C.
odf init¶
Scaffolds a new project — a config.toml and an importable app package that
registers components via decorators (@Entity, @Component, @Repository, ...).
NAME— optional. If given, creates and scaffolds a new subdirectory./NAME. If omitted, scaffolds into the current directory. Either way, the target must not already contain files.--template/-t— which starting layout to scaffold. Defaults todefault.
No template needs a dependency of its own: each is built on opendataframework
plus the Python standard library (sqlite3 for storage). Running one with the
UI, as odf run does by default, needs the odf[ui] extra.
Templates¶
Every template starts from default's layout (one
Entity, one Repository, one sqlite3-backed Storage) and adds one
thing on top. Each has its own page with the full folder layout and what
gets registered:
| Template | Adds on top of default |
|---|---|
default |
— nothing; this is the starting point itself |
data-analytics |
An @Analytics @Task that aggregates repository data and writes a JSON report |
data-science |
A seed CSV and a notebook that loads it into the repository |
data-engineering |
A SeedItems → ExportItemsSummary Pipeline reading data/raw/ and writing data/processed/ |
research |
A RunExperiment Task that loads data/items.csv and writes results/summary.json, plus a write-up stub |
data-science, data-engineering, and data-analytics all borrow folder names from
cookiecutter-data-science,
the most widely used Python data-science project template — each ODF template takes
just the piece relevant to its usecase rather than the whole layout. data-science
and data-engineering use its data/raw/ (source data, never edited in place) →
data/processed/ (derived output) split, expressed here with ODF's own
Task/Pipeline abstractions instead of a separate orchestration tool.
data-analytics uses its reports/ folder instead, since analytics is
consumption-oriented: it reads repository data and produces a report artifact
rather than ingesting one. research follows "Good Enough Practices in Scientific
Computing" (Wilson et al., 2017): a
flat data/ for raw, read-only input, a results/ for everything generated, and a
doc/ for the write-up — app/ plays the role of that layout's src/.
Next steps:
cd my-pipeline
odf run
odf run¶
Starts an existing project: imports its app package (registering all decorated
components as a side effect), loads its config, and runs until Ctrl+C.
Run it from the project's root directory — the one containing config.toml and
the app package, the same layout odf init produces.
| Argument / Option | Default | Description |
|---|---|---|
CONFIG |
config.toml |
Path to a config file or a directory of config files (see Project) |
--app |
app |
Import name of the package that registers components — see Server for the same convention used when building a Server directly in Python |
--ui / --no-ui |
--ui |
Start the UI |
--ui-host, --ui-port |
127.0.0.1, 4747 |
Interface/port for the UI |
--theme |
config's [ui] theme, or default |
UI theme (visual file-set) to serve. Built in: default, glitch, neo, emerald, onyx (see UI) |
--mcp / --no-mcp |
--no-mcp |
Start the MCP server |
--mcp-host, --mcp-port |
127.0.0.1, 4748 |
Interface/port for the MCP server |
--chat / --no-chat |
--no-chat |
Add a chat window to the UI (requires --ui) |
When opendataframework or odf rejects the project at start-up, odf run
prints the reason on one line and exits with status 1, without a traceback.
When the error comes from a decorator, the line ends with the file and line of
the decorated class:
$ odf run
Error: Repository expects a class registered with @Entity, got 'Item'. Decorate it with @Entity — or, if Item is the repository itself, pass its entity: @Repository(SomeEntity) (app/repositories.py:8)
An exception raised by the project's own code, such as a constructor or a
setup(), is shown with its full traceback.
The UI (--ui, on by default) requires the odf[ui] extra
(fastapi/uvicorn); pass --no-ui to run without it. --mcp requires
odf[mcp] and --chat requires odf[chat].