Skip to content

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:

pip install "odf[ui]"Installed
$ 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, ...).

odf init [NAME] [--template/-t TEMPLATE]
  • 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 to default.

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/.

odf init my-pipeline --template data-engineeringCreated 'data-engineering' project 'my-pipeline' in /path/to/my-pipeline
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.

odf run [CONFIG] [OPTIONS]

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)
$ odf run
UI running at http://127.0.0.1:4747
Press Ctrl+C to stop

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].