Skip to content

The jarvis CLI

Two different things share the jarvis name:

  • ./jarvis — the root dev-entrypoint script (bash). Drives Docker Compose: bring the stack up, tail logs, run tests, reset to a clean slate.
  • the containerized CLI — a Python package (cli/src/jarvis_cli) that scaffolds and enables modules and prepares a deploy. ./jarvis forwards any verb it doesn't recognize straight into this container.

./jarvis verbs

Verb What it does
up Ensures .env exists (copies it from .env.example on first run), preflight-checks Docker, assembles enabled modules' migrations into the image-baked dir, refreshes the scheduler's crontab, then runs docker compose up -d --build. Prints the PocketBase admin URL and the dev user's email.
down [args] docker compose down (extra args are forwarded).
logs [svc] docker compose logs -f — all services, or just svc if given.
test Runs the pytest suites (agent-runtime, cli, docker/bootstrap) inside a throwaway python:3.13-slim container — no host Python needed.
reset down --volumes, re-creates .env if missing, re-assembles migrations and crontab, then up -d --build. A clean slate: named volumes (PocketBase data, vault) are dropped.
cli [args] Runs the containerized CLI: docker compose --profile cli run --rm cli <args>. Equivalent to invoking an unknown verb (below), spelled out explicitly.
doctor Checks Docker is installed and running, .env is present, and (if fvm is installed) that it's pinned to the Flutter version in .fvmrc.
help Prints usage and the note that unknown verbs are forwarded.

Docker preflight

Every verb that drives Docker — up, down, logs, test, reset, cli, and the unknown-verb forward path — first runs a preflight that aborts with a clear message if Docker isn't installed or isn't running. doctor and help don't need Docker and skip it.

Unknown verbs forward to the containerized CLI

Anything that isn't one of the verbs above — e.g. ./jarvis module new foo — is passed straight through as docker compose --profile cli run --rm cli <verb> <args>. That's how the module-scaffolding and deploy commands below are actually invoked; ./jarvis cli ... and the bare forwarded form are equivalent.

The forwarded CLI commands

These run inside the cli container (cli/src/jarvis_cli), with the repo mounted at /workspace.

jarvis module new <name>

Scaffolds a new module under modules/<name>/ from the module template.

./jarvis module new my_module --title "My Module" --identity personal
  • --title — display title (defaults to the capitalized module name, e.g. my_moduleMy_module, if omitted).
  • --identity — one of personal, freelance, rotary, shared (default personal).

Fails loudly (exit 1) if the module directory already exists.

jarvis module add <name>

Enables an already-scaffolded module and regenerates every generated artifact from modules.yaml + every enabled module's module.yaml:

./jarvis module add my_module

This adds my_module to the enabled list, then regenerates:

  • app/lib/generated/enabled_modules.dart — the Flutter tab registry.
  • backend/generated/manifest.json — the module manifest the backend and jarvis deploy read.
  • backend/generated/crontab — the scheduler's supercronic crontab, built from every enabled module's schedules:.
  • app/pubspec.yaml — the managed dependency block pointing at each surfaced module's Flutter package.

jarvis deploy

Stages the real migration set and reports what a deploy would do — it runs no Docker:

./jarvis deploy

It assembles every enabled module's migrations into the image-baked staging dir, lists the full baked migration set (core + modules, in manifest order), echoes the multi-arch build/push commands (placeholders — docker buildx build --platform linux/amd64,linux/arm64 ...), and prints the scheduler crontab that would ship.

JARVIS_DRY_RUN

Set JARVIS_DRY_RUN=1 to make ./jarvis echo the Docker Compose commands it would run instead of executing them — no Docker required. This is what the wrapper's own test suite uses to exercise verb dispatch without a real stack:

JARVIS_DRY_RUN=1 ./jarvis up