Skip to content

Installation

Valved is a Python CLI plus a Postgres-backed state store. It is Postgres-from-day-one — there is no SQLite fallback.

  • Python 3.11+
  • Postgres 14+ — either the bundled docker-compose.yml (recommended for local dev) or your own (managed RDS, Cloud SQL, Supabase, etc.)
  • Docker — only if you use the bundled Postgres path. valved init checks for it up front: no Docker and no --external-postgres and it exits 3 with a message telling you to do one or the other, before writing anything.
  • An Anthropic API key (or Claude OAuth token) for the AI harness — see Configuration

Pick your favorite Python tool:

Terminal window
pipx install valved
# or
uv tool install valved
# or
pip install --user valved

After install, valved version should work.

Terminal window
mkdir my-valved-project && cd my-valved-project
valved init # writes valved.toml, valved/, .env.example, .gitignore, docker-compose.yml
docker compose up -d # starts Postgres on 127.0.0.1:5432
valved serve # API + scheduler + reaper + archiver + worker pool

Behind the scenes:

  • valved init writes valved.toml, the valved/ config dir (connections.toml, models.toml, runner.toml, and the memory files), .env.example, .gitignore, an empty el/, and docker-compose.yml (the bundled-Postgres template). It also runs git init unless you pass --no-git-init.
  • valved init then tries to bring the state-store schema to head. With bundled Postgres it usually can’t — the compose file was only just written — so it prints Postgres isn't running yet — schema not initialized and moves on. That is expected, not an error.
  • docker compose up -d brings up Postgres at the URL the .env template expects: postgresql+psycopg://valved:valved@127.0.0.1:5432/valved.
  • valved serve brings the schema to head, then starts accepting CLI / REST / MCP requests.

valved init takes --project-name <name> to override the project name (there is no --name), --default-target <name> to name the default target something other than dev, and --with-dbt / --with-dlt (or the --dbt-path / --dbt-url / --dlt-path / --dlt-url brownfield variants) to scaffold or adopt components.

Running more than one Valved project on one machine

Section titled “Running more than one Valved project on one machine”

Containers and volumes are namespaced per project, but the host port is not: every bundled project’s DATABASE_URL defaults to 127.0.0.1:5432/valved. The second project’s Postgres cannot bind the port, and its commands resolve to whichever store is already listening there.

Give each project its own port before valved init, setting both values in that project’s .env — they have to agree:

Terminal window
VALVED_POSTGRES_PORT=5433
DATABASE_URL=postgresql+psycopg://valved:valved@127.0.0.1:5433/valved

If you skip this, valved init notices rather than proceeding. Since 0.4.4 it refuses to run migrations against a database that already holds a Valved schema, exiting 2 and naming what it found. Pass --adopt-existing only if sharing that store is genuinely what you want — and note that pipelines are keyed by name alone, so two projects’ pipelines with the same name are the same row.

Re-running valved init in a directory that already has a valved.toml is unaffected: that is the project’s own claim on its store, so upgrades still work without a flag.

If you already operate Postgres (managed RDS / Cloud SQL / Supabase / a local install):

Terminal window
valved init --external-postgres "postgresql+psycopg://user:pass@host:5432/db"
# add the DATABASE_URL line init prints to .env, then:
valved serve

--external-postgres does two things: it skips the docker-compose.yml scaffolding, and it treats that Postgres as already-running — init connects and runs the migrations immediately. If the host is unreachable or the user can’t CREATE TABLE, init exits 3 after writing the project files.

It does not write your connection string into .env. Deliberately: the URL carries a password and .env.example is a committed file. init prints the line for you to paste into the gitignored .env, and leaves only a commented placeholder in .env.example:

! External Postgres: bundled docker-compose not generated. Valved will not
manage your Postgres lifecycle (backups, upgrades, tuning are yours).
Add this line to your .env (gitignored):
DATABASE_URL=postgresql+psycopg://user:pass@host:5432/db

The URL is used as-is for that one migration and stored nowhere. Afterwards every command resolves the state store from the DATABASE_URL env var, falling back to the bundled default postgresql+psycopg://valved:valved@localhost:5432/valved. So until you add that line to .env, valved serve points at a bundled Postgres you never started.

The harness needs a model provider. Set one before you plan or build:

Terminal window
cp .env.example .env
# then edit .env to add ANTHROPIC_API_KEY (or a Claude OAuth token)
valved auth status # verify the harness can see a credential

See Configuration → valved/models.toml for API-key vs OAuth and model tiers.

Terminal window
curl -s http://127.0.0.1:8765/healthz # liveness
curl -s http://127.0.0.1:8765/readyz # readiness (200 once migrations are at head)
valved runs

readyz is 200 only when Postgres is reachable and the schema is at head. Anything else is a 503 whose body names the reason — database unreachable: <ExceptionClass> (usually a DATABASE_URL pointing somewhere that isn’t there) or migrations not at head (at <rev>, head <rev>). Both /healthz and /readyz are unauthenticated probes.

valved init --with-dbt gets you a dbt project, but not a runnable one. Two things are still missing and neither is written for you:

  • A [components.dbt] block in valved.toml, and valved connect dbt to install and pin the engine. Without it the dbt engineer is never granted its dbt_verify tool, so it authors models without executing them.
  • A profiles.yml. Nothing in Valved generates one. dbt run by hand fails until you supply it.

Both are covered in step 4 of the Quickstart.

  • Quickstart — build your first pipeline end-to-end
  • The core loop — how plan → build → run → deploy fit together
  • MCP server — drive Valved from Claude Desktop / Cursor / Claude Code