Local mode
autoair local runs the standalone server with a settings preset for a single user on a workstation. It needs no Airflow server: you design, validate, preview and deploy DAG files, then run them in an Airflow of your choice.
Install and start
autoair local needs the standalone extra (uvicorn) and something to put in the operator palette. The airflow extra installs Apache Airflow and the standard provider, which gives you BashOperator, PythonOperator, EmptyOperator, the standard sensors and the DagBag import check.
# one-off, with uv
uvx --from 'autoair[standalone,airflow]' autoair local --open
# or in a virtual environment
python -m venv .venv && . .venv/bin/activate
pip install 'autoair[standalone,airflow,format]'
autoair local --open
Released versions come from PyPI (published by the release workflow on v* tags). For an unreleased commit, install the wheel built by make build (pip install 'dist/autoair-<version>-py3-none-any.whl[standalone,airflow]') or run from a source checkout.
From a source checkout, uv sync installs the development group (which already contains Airflow and uvicorn); build the frontend once:
uv sync
(cd frontend && npm ci && npm run build)
uv run autoair local --open
The command prints where it writes and a sign-in link with a random access token created for this run:
AutoAir (local mode): DAGs in dags
Open http://127.0.0.1:8765/ui/#token=autoair-local-...
(this per-run link signs you in; keep it to yourself)
--open opens that link. The UI keeps the token for the browser tab and removes it from the address bar; the token sits in the URL fragment, which the browser never sends to a server. The holder of the token gets local.roles (default ["Admin"]: edit, validate, deploy). Other programs and web pages on your machine cannot use the API without it. After a restart the old link no longer works: open the new one.
uvx autoair local without extras does not start: the core package has no HTTP server. The command exits with code 1 and says which extras to install: "autoair local needs an HTTP server, which comes with the 'standalone' extra (uvicorn). Install it with: pip install 'autoair[standalone,airflow]'", followed by the uvx --from 'autoair[standalone,airflow]' autoair local --open form. Without Airflow or providers installed, the palette shows no operators.
Options
| Option | Environment variable | Default | Effect |
|---|---|---|---|
--dags-folder PATH | (sets AUTOAIR_DAGS_FOLDER) | ./dags | Folder the spec and generated files are written to. Local mode writes directly into it (no autoair/ sub-folder). |
--host HOST | 127.0.0.1 | Bind address. Keep it on loopback. | |
--port PORT | 8765 | Port. | |
--token TOKEN | AUTOAIR_LOCAL__TOKEN | a random token per run | Require this access token instead of a generated one. The sign-in page shows "This local server requires an access token (autoair local --token)." API clients send Authorization: Bearer <token>. |
--no-token | off | Serve without authentication (loopback only). Visitors get iam.anonymous_roles, default ["Viewer"] (read-only); set AUTOAIR_IAM__ANONYMOUS_ROLES='["Admin"]' to let them edit and deploy. Requests whose Host or Origin is not a loopback address (or the host of server.public_url) get 403. | |
| (config only) | AUTOAIR_LOCAL__ROLES | ["Admin"] | AutoAir roles of the token holder; never deploy:direct_push. |
--open / --no-open | AUTOAIR_LOCAL__OPEN_BROWSER | off | Open the UI in the default browser once /api/health answers. |
--config FILE, -c FILE | AUTOAIR_CONFIG_FILE | none | Configuration file (YAML, JSON, INI, Python); repeatable. |
Binding anything other than a loopback address requires a token you set yourself:
autoair local --host 0.0.0.0 --token "$(openssl rand -hex 16)"
Without a token the command exits with code 2: refusing to serve 0.0.0.0 without --token: local mode has no other authentication.
What the preset changes
Local mode applies these settings on top of your configuration:
| Setting | Value in local mode | Consequence |
|---|---|---|
mode | local | |
dags_folder / subfolder | --dags-folder (default dags) / empty | Files go straight into the folder; AutoAir state goes into <dags_folder>/.autoair |
features.runs, features.test_runs, features.airflow | false | No trigger, backfill, clear, test runs, run overlay, task logs, connection/pool/variable pickers, DAG status, or import from Airflow |
catalog_strategy | static | Operators are found by parsing installed packages, nothing is imported |
import_check_on_deploy | true only when Airflow is importable | Deploys run the DagBag import check if Airflow is installed |
dagbag_pool | false | One import check at a time, no warm worker pool |
sso.enabled | false | No Airflow sign-in |
Everything else (policy rules, environments, templates, AI, a Git deploy target) is configured as usual. For example, to deploy to a Git repository instead of ./dags:
export AUTOAIR_STORAGE__MODE=git
export AUTOAIR_STORAGE__GIT__PROVIDER=local
export AUTOAIR_STORAGE__GIT__REPO=git@github.com:acme/airflow-dags.git
export AUTOAIR_STORAGE__GIT__SUBDIR=dags
export AUTOAIR_STORAGE__GIT__MODE=push
autoair local
provider=local drives the git command-line tool against any remote and pushes the pending branch without opening a pull request. github, gitlab, bitbucket and azure use the host's REST API, and gitea (Gitea or Forgejo) pushes with the git CLI and opens pull requests through the Gitea API; these five open pull requests in storage.git.mode=pr (the default) with AUTOAIR_STORAGE__GIT__TOKEN. See Deploy and Git bundles.
Adding operators
The palette lists what is installed next to AutoAir. Add providers to the same environment:
uvx --from 'autoair[standalone,airflow]' \
--with apache-airflow-providers-amazon \
--with apache-airflow-providers-common-sql \
autoair local
Custom operators in a folder are found with AUTOAIR_CUSTOM_OPERATOR_PATHS='["/path/to/include"]', and internal operator packages with AUTOAIR_EXTRA_OPERATOR_PACKAGES or AUTOAIR_EXTRA_OPERATOR_DISTRIBUTIONS. The catalog is cached on disk (AUTOAIR_CACHE_DIR, default $XDG_CACHE_HOME/autoair) and rebuilt when the installed packages change. See Catalog sources.
Running the DAGs
Local mode does not talk to Airflow. To run what you built, point an Airflow at the same folder (for example AIRFLOW__CORE__DAGS_FOLDER=$PWD/dags airflow standalone) or push to the repository your Airflow reads. When you need runs, logs and pickers inside AutoAir, switch to the plugin or standalone mode; specs written in local mode are read unchanged.
Security notes
- Anyone holding the token has
local.roles(default Admin). Do not share the sign-in link; with--tokenkeep the token secret. - With
--no-token, anyone who can reach the loopback port hasiam.anonymous_roles(default Viewer). Other users of a shared machine can reach it. - Python task bodies and inline functions are imported by the
DagBagcheck in a subprocess on your machine. Do not deploy specs from untrusted sources without reviewing them.