Otto Docs
Deployment

Development Environment

This guide covers setting up a local development environment for working on Otto.

This guide covers setting up a local development environment for working on Otto.

Prerequisites

Before you start, make sure you have the following installed:

  • Docker and Docker Compose (v2+) -- required for the backend, worker, and Redis
  • Node.js 18+ and npm -- required for the frontend dev server
  • An LLM API key from one of the supported providers:

Starting Development Mode

Run the following from the project root:

./otto dev

Or equivalently:

make dev

If this is your first time running Otto, the CLI will launch an interactive configuration wizard to set up your .env file. You can re-run it at any time with ./otto configure.

What Happens on Startup

The ./otto dev command orchestrates three things:

  1. Backend services start in Docker. The backend API, ARQ worker, and Redis are launched via docker-compose.dev.yml. The backend container is built from your local ./backend source code, with the source directory mounted into the container for live editing.

  2. The CLI waits for the backend to become healthy. It polls http://localhost:8000/api/health for up to 60 seconds before proceeding.

  3. The frontend starts natively on your host. The Next.js dev server runs outside Docker (via npm run dev in frontend/), giving you the fastest possible hot reload for frontend changes.

Once everything is running, Otto is available at:

Hot Reload

Both the backend and frontend support automatic reloading when you edit code.

Backend API (FastAPI)

The backend runs with uvicorn --reload, which watches for Python file changes and restarts the server automatically. Because ./backend is bind-mounted into the container at /app, any file you edit on your host is immediately visible inside the container.

ARQ Worker

The async task worker runs under watchmedo auto-restart, which monitors all .py files in the /app/app directory. When you change any Python file, the worker process restarts automatically. The full command is:

watchmedo auto-restart --directory=/app/app --pattern="*.py" --recursive -- \
  python -m arq app.arq_worker.WorkerSettings

Frontend (Next.js)

The Next.js dev server runs natively on your host machine (not in Docker), so React fast refresh works as expected. Editing any component, page, or stylesheet triggers an instant browser update.

Viewing Logs

When you run ./otto dev, backend and worker logs are streamed to your terminal with color-coded prefixes:

  • [backend] -- cyan -- FastAPI server logs
  • [worker] -- yellow -- ARQ worker logs

Frontend logs appear inline from the Next.js dev server running in the foreground.

To view logs from a separate terminal, or to filter by service:

# All backend services
./otto logs
 
# Backend API only
./otto logs otto-backend
 
# Worker only
./otto logs arq-worker
 
# Redis only
./otto logs redis

Stopping Development Mode

Press Ctrl+C in the terminal where ./otto dev is running. The CLI will:

  1. Stop the background log streaming
  2. Run docker compose down to stop all backend containers
  3. Print "Stopped."

You can also stop services from another terminal:

./otto stop

Running Tests

cd backend
source venv/bin/activate
pytest tests/ -v

If you do not have a local virtualenv set up, you can run tests inside the backend container:

docker compose -f docker-compose.dev.yml exec otto-backend pytest tests/ -v

Common Development Tasks

Rebuilding After Dependency Changes

If you add or change Python dependencies in requirements.txt, rebuild the backend container:

make dev-build

This runs docker compose -f docker-compose.dev.yml build --no-cache to rebuild from scratch, then you can start dev mode again with ./otto dev.

For frontend dependency changes, stop the dev server and run:

cd frontend
npm install

Then restart with ./otto dev.

Resetting Data

To wipe all local data (databases, Redis state, uploads) and start fresh:

make clean

This removes files from data/sqlite, data/redis, and data/team_memory while preserving the directory structure. Restart Otto afterward to reinitialize.

Reconfiguring

To change your LLM provider, add integrations, or update API keys:

./otto configure

The wizard shows your current values and lets you update individual sections. Press Enter to keep any existing value.

Checking Service Health

./otto status

This shows running containers and checks whether the backend and frontend are responding.

For a detailed health check with JSON output:

make health

Project Structure

otto/
  backend/                  # Python FastAPI server
    app/
      agent/                # LangGraph AI agent
      routers/              # API endpoints
      tools/                # Built-in tools
      skills/               # Skill system
      database/             # Redis + SQLite storage
      mcp/                  # Model Context Protocol
    skills-defaults/        # Default skills baked into Docker image
    requirements.txt
    Dockerfile
  frontend/                 # Next.js 15 web application
    app/                    # Pages (App Router)
    components/             # React components
      ui/                   # shadcn/ui components
    types/                  # TypeScript type definitions
    lib/                    # Utility functions
    package.json
  data/                     # Runtime data (gitignored)
    sqlite/                 # SQLite database files
    redis/                  # Redis persistence
    sandbox/                # Agent file workspace
    uploads/                # User-uploaded files
    team_memory/            # Vector memory store
  skills/                   # Skill definitions (volume-mounted)
  logs/                     # Application logs
  scripts/                  # Backup, restore, and helper scripts
  docs/                     # Documentation
  docker-compose.yml        # Production compose file
  docker-compose.dev.yml    # Development compose file
  otto                      # CLI entry point
  Makefile                  # Convenience targets

Key Differences Between Dev and Production

AspectDevelopmentProduction
Backend imageBuilt from local sourcePre-built from GHCR
Backend reloaduvicorn --reloadStandard uvicorn
Worker reloadwatchmedo auto-restartStandard arq
FrontendNext.js dev server on hostStatic export served by nginx
Redis portExposed on host (6379)Internal only
Source mounting./backend mounted into containerNo source mounting
Env hintFASTAPI_ENV=developmentNot set