Otto Docs
Deployment

CLI Reference

The `otto` command is the primary interface for managing your Otto installation. It is a Bash script located at the project root and can be invoked as `./otto` from the project directory or simply ...

The otto command is the primary interface for managing your Otto installation. It is a Bash script located at the project root and can be invoked as ./otto from the project directory or simply otto if the symlink in /usr/local/bin has been set up (done automatically during installation and updates).

Commands

otto start

Start Otto in production mode.

Usage: otto start

Starts all services using pre-built container images from the GitHub Container Registry. On first run, or if the .env file is missing an LLM provider configuration, the interactive setup wizard runs automatically.

What it does:

  1. Checks that Docker is installed and running
  2. Ensures .env exists and has an LLM provider configured (runs otto configure if not)
  3. Creates data directories: data/sqlite, data/redis, data/sandbox, data/uploads, data/team_memory, logs, skills
  4. Runs docker compose -f docker-compose.yml up -d
  5. Reports that Otto is running at http://localhost:3000

Services started: redis, backend, arq-worker, frontend

Example:

$ otto start
Starting Otto...
Otto is running at http://localhost:3000

otto stop

Stop all Otto services.

Usage: otto stop

Shuts down containers from both the production and development Compose files. Silently handles cases where one or both are not running.

Example:

$ otto stop
Stopping Otto...
Stopped.

otto restart

Restart all running services.

Usage: otto restart

Restarts containers without recreating them. Tries the production Compose file first, then the development Compose file. Reports an error if no running containers are found.

Example:

$ otto restart
Restarting Otto...
Done.

otto dev

Start the development environment with hot reload.

Usage: otto dev

Starts backend services in Docker (built from local source) and the frontend natively on the host. All Python code changes trigger automatic restarts. Press Ctrl+C to stop everything.

What it does:

  1. Checks that Docker, Node.js (18+), and npm are installed
  2. Ensures .env exists and has an LLM provider configured
  3. Creates data directories
  4. Installs frontend npm dependencies if node_modules/ is missing
  5. Starts backend, arq-worker, and Redis via docker-compose.dev.yml
  6. Waits for backend health check at http://localhost:8000/api/health (up to 60 seconds)
  7. Streams backend and worker logs with color-coded prefixes ([backend] in cyan, [worker] in yellow)
  8. Starts the Next.js dev server natively on the host
  9. On Ctrl+C: stops log streaming, runs docker compose down, reports "Stopped."

Key differences from production:

  • Backend is built from local ./backend source
  • Backend runs with uvicorn --reload
  • ARQ worker runs with watchmedo auto-restart
  • Frontend runs natively (not in Docker)
  • Redis port 6379 is exposed to the host

Example:

$ otto dev
Starting Otto in development mode...
Building backend from local source...
Waiting for backend to be ready...
Backend is healthy.
[backend] INFO:     Uvicorn running on http://0.0.0.0:8000
[worker]  Worker started, processing tasks...
 Next.js 15.x
  - Local: http://localhost:3000

otto status

Show service status and health.

Usage: otto status

Displays the state of all running containers and checks whether the backend and frontend are responding.

What it does:

  1. Shows docker compose ps output for running containers
  2. Checks backend health at http://localhost:8000/api/health
  3. Checks frontend availability at http://localhost:3000
  4. Reports each as "healthy" or "not responding"

Example:

$ otto status
NAME            STATUS          PORTS
otto-backend    Up 2 hours      0.0.0.0:8000->8000/tcp
otto-frontend   Up 2 hours      0.0.0.0:3000->3000/tcp
otto-arq-worker Up 2 hours
redis           Up 2 hours
 
Backend:  healthy
Frontend: healthy

otto logs

Tail logs from running containers.

Usage: otto logs [service]

Streams live log output. When called without arguments, shows logs from all services. Specify a service name to filter.

Arguments:

ArgumentDescription
(none)Logs from all services
otto-backendBackend API server logs
arq-workerAsync task worker logs
redisRedis server logs
otto-frontendFrontend nginx logs

Examples:

# All services
$ otto logs
 
# Backend only
$ otto logs otto-backend
 
# Worker only
$ otto logs arq-worker

otto configure

Interactive setup wizard for API keys and integrations.

Usage: otto configure

Walks through each configuration section and writes the results to .env. If no .env file exists, it starts from .env.example as a template.

Configuration sections:

  1. LLM Provider (required) -- Gemini, OpenAI, or Ollama
  2. Web Search -- Tavily API key
  3. Specialization -- Agent focus area
  4. Slack Integration -- Bot token and signing secret
  5. Email Integration -- SMTP and IMAP settings
  6. Redis Password -- Authentication for Redis
  7. LangSmith Tracing -- Observability and debugging

At every prompt, the current value is shown in brackets. Press Enter to keep it. Secret values are masked, showing only the first and last 4 characters.

Example:

$ otto configure
 
=== Otto Configuration ===
 
1. LLM Provider (required)
Current provider: Gemini
API key: [GOOG****abcd]
Keep current provider? [Y/n]:

otto sync-settings

Merge your .env with the latest configuration template.

Usage: otto sync-settings

Reads .env.example line by line and produces an updated .env that:

  • Keeps all your existing values for settings that exist in the template
  • Adds new settings from the template with their default values
  • Preserves any custom settings you have added that are not in the template (appended under a "Custom settings" section)

This command runs automatically as part of otto update, but you can run it manually after pulling new code.

Example:

$ otto sync-settings
Settings synced with latest template.

otto update

Pull the latest version and restart.

Usage: otto update

Performs a complete in-place upgrade of your Otto installation.

Update steps:

  1. Downloads the latest CLI script, Compose files, and configuration templates from GitHub
  2. Sets executable permissions on scripts
  3. Updates default skills (without overwriting user-modified skills)
  4. Ensures the /usr/local/bin/otto symlink points to your installation
  5. Syncs new configuration options into your .env (preserves your values)
  6. Pulls the latest Docker images from the container registry
  7. Recreates all containers with the new images

Your data is preserved. If GITHUB_TOKEN is set in the environment, it is used for authenticated downloads.

Example:

$ otto update
Downloading latest files...
Syncing settings...
Pulling latest images...
Recreating containers...
Otto has been updated and restarted.

otto backup

Create a backup of all Otto data.

Usage: otto backup

Otto must be running when you create a backup (the script needs access to the Redis container to trigger a snapshot).

What is backed up:

FileContents
sqlite_data.tar.gzSQLite database (users, tasks, logs, projects, schedules)
redis_dump.rdbRedis snapshot (queues, checkpoints, cached state)
.envEnvironment configuration and secrets

Backup location: backups/YYYY-MM-DD_HH-MM-SS/ in the project root.

Example:

$ otto backup
Creating backup...
Backup saved to backups/2026-02-19_14-30-00/

otto restore

Restore from a backup directory.

Usage: otto restore <backup-directory>

Restores data from a previously created backup. This command stops all running Otto containers before restoring and does not restart them automatically. You must start Otto manually after the restore completes.

Arguments:

ArgumentDescription
<backup-directory>Path to the backup directory (e.g., backups/2026-02-19_14-30-00)

What it does:

  1. Validates the backup directory exists
  2. Stops all running Otto containers
  3. Restores SQLite data from sqlite_data.tar.gz
  4. Restores Redis dump from redis_dump.rdb
  5. Restores .env

Example:

$ otto restore backups/2026-02-19_14-30-00
Stopping Otto...
Restoring SQLite data...
Restoring Redis data...
Restoring environment config...
Restore complete. Start Otto with: otto start

otto help

Show available commands.

Usage: otto help
       otto --help
       otto -h

Prints a summary of all available commands and their descriptions.


Makefile Targets

The project includes a Makefile that wraps CLI commands and adds a few extras. All targets are run from the project root.

TargetEquivalentDescription
make devotto devStart development environment
make dev-build(direct docker compose)Rebuild backend container from scratch (no cache)
make startotto startStart production environment
make stopotto stopStop all containers
make restartotto restartRestart all containers
make updateotto updatePull latest and restart
make statusotto statusShow container status
make health(direct curl)Check backend health with formatted JSON output
make logsotto logsShow all container logs
make logs-backendotto logs otto-backendBackend logs only
make logs-redisotto logs redisRedis logs only
make backupotto backupCreate backup
make restore FILE=<dir>otto restore <dir>Restore from backup
make clean(direct commands)Remove all data files, keep directory structure
make export-traces(direct python)Export LangSmith traces to JSON

The export-traces target accepts optional parameters:

make export-traces DAYS=14 LIMIT=100 PROJECT=my-project

Common Workflows

First Installation

git clone https://github.com/agent-otto/otto.git
cd otto
./otto configure    # Set up LLM provider and integrations
./otto start        # Start production services

Open http://localhost:3000 and follow the onboarding flow.

Daily Development

cd otto
./otto dev          # Start dev mode with hot reload
# ... edit code, changes reload automatically ...
# Ctrl+C to stop

Production Update

./otto backup       # Back up before updating
./otto update       # Pull latest version and restart
./otto status       # Verify everything is healthy

Disaster Recovery

./otto restore backups/2026-02-19_14-30-00
./otto start
./otto status

Switching LLM Providers

./otto configure    # Select new provider in section 1
./otto restart      # Apply changes

Adding Slack Integration

./otto configure    # Fill in Slack section
./otto restart      # Apply changes