# Oduflow

> AI-first Odoo development and CI tool powered by reusable database templates. Provisions isolated, ephemeral Odoo environments on Docker — one per git branch — and exposes them to AI coding agents via MCP.

## Installation

### System Requirements

- Docker (Docker Engine or Docker Desktop)
- Python 3.10+
- Git
- fuse-overlayfs (for filestore overlay mounting)

### Step 1: Install fuse-overlayfs

```bash
sudo apt install fuse-overlayfs
```

Enable `user_allow_other` in `/etc/fuse.conf`:

```bash
sudo sed -i 's/^#user_allow_other/user_allow_other/' /etc/fuse.conf
```

### Step 2: Install Oduflow

Recommended — install via [uv](https://docs.astral.sh/uv/):

```bash
uv tool install oduflow
```

Alternative — install via pip:

```bash
pip install oduflow
```

For local development:

```bash
git clone https://github.com/oduist/oduflow.git
cd oduflow
uv sync          # or: python -m venv .venv && pip install -e .
```

### Step 3: Configure

All settings are configured via environment variables. On servers, `oduflow init-instance` seeds the file at `/etc/oduflow/instance_{ID}.env` and `oduflow run-instance` picks it up automatically. For local development, pass the path explicitly:

```bash
oduflow --env .env run-instance
```

Key environment variables:

- `ODUFLOW_TRANSPORT` — `http` (default) or `stdio`
- `ODUFLOW_HOST` — bind address (default `0.0.0.0`)
- `ODUFLOW_PORT` — HTTP port (default `8000`)
- `ODUFLOW_AUTH_TOKEN` — Bearer token for MCP auth (empty = auth disabled)
- `ODUFLOW_UI_PASSWORD` — password for Web UI Basic Auth (empty = UI open)
- `ODUFLOW_DATA_DIR` — base directory for all data (default `/srv/oduflow`)
- `ODUFLOW_ETC_DIR` — config/credentials directory (default `/etc/oduflow` in Docker, `~/.oduflow/conf` locally)
- `EXTERNAL_HOST` — hostname for environment URLs (default `localhost`)
- `ODUFLOW_ROUTING_MODE` — `port` (default) or `traefik` (auto-HTTPS)
- `ODUFLOW_OVERLAY_THRESHOLD_MB` — filestore size threshold for overlay vs copy (default `50`)
- `ODUFLOW_STATELESS_HTTP` — stateless MCP HTTP mode (default `true`); set to `false` for session-based communication
- `ODUFLOW_INSTANCE_ID` — instance identifier for multi-instance setups (default `1`)
- `ODUFLOW_TRACE` — set to `1` for trace-level logging

### Step 4: Initialize the system

```bash
# Initialize shared infrastructure (network, DB, Traefik)
oduflow init

# Initialize per-instance directories (workspaces, templates)
oduflow init-instance --instance 1
```

This creates the shared Docker network, PostgreSQL container, and (optionally) Traefik reverse proxy. `init-instance` seeds `/etc/oduflow/instance_1.env` from the bundled `.env.example` — edit it before starting the server.

### Step 5: Set up a template

**From scratch (no production dump):**

```bash
oduflow init-template --odoo-image odoo:17.0
```

**From a production dump:**

Place `dump.sql` (or `dump.pgdump`) and `filestore/` directory into `$ODUFLOW_DATA_DIR/instance_{ID}/templates/default/`, then:

```bash
oduflow reload-template
```

### Step 6: Start the MCP server

```bash
oduflow run-instance
```

The server starts on `http://0.0.0.0:8000`. MCP endpoint: `http://<host>:8000/mcp`.

### Step 7 (optional): Auto-start with systemd

```bash
# Install and enable systemd service for instance 1
oduflow systemd-install --instance 1

# Manage the service
systemctl start oduflow
systemctl status oduflow
journalctl -u oduflow -f

# Remove the service
oduflow systemd-uninstall --instance 1
```

## MCP Client Configuration

### Cursor / Windsurf

`.cursor/mcp.json` or `.windsurf/mcp.json`:

```json
{
  "mcpServers": {
    "oduflow": {
      "type": "http",
      "url": "https://<your-oduflow-host>/mcp",
      "headers": {
        "Authorization": "Bearer <your-token>"
      }
    }
  }
}
```

### Amp

`.amp/settings.json`:

```json
{
  "mcpServers": {
    "oduflow": {
      "type": "http",
      "url": "https://<your-oduflow-host>/mcp",
      "headers": {
        "Authorization": "Bearer <your-token>"
      }
    }
  }
}
```

### Claude Desktop

`claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "oduflow": {
      "type": "http",
      "url": "https://<your-oduflow-host>/mcp",
      "headers": {
        "Authorization": "Bearer <your-token>"
      }
    }
  }
}
```

## Core MCP Tools

- `create_environment` — provision a new Odoo environment for a branch
- `delete_environment` — tear down an environment
- `start_environment` / `stop_environment` / `restart_environment` — lifecycle control
- `install_odoo_modules` — install Odoo modules
- `upgrade_odoo_modules` — upgrade Odoo modules
- `run_odoo_tests` — run Odoo tests for specific modules
- `pull_and_apply` — pull latest code and auto-install/upgrade/restart as needed
- `get_environment_logs` — retrieve container logs
- `exec_in_odoo` — execute shell commands inside the Odoo container
- `read_file_in_odoo` — read a text file or list a directory inside the container (supports line ranges)
- `run_db_query` — execute SQL queries against the environment's PostgreSQL database
- `reset_admin_password` — reset the admin user password (default: "test")
- `list_environments` / `get_environment_info` — inspect environments
- `rebuild_environment` — re-create the container from the same image, preserving DB and filestore
- `create_service` / `delete_service` / `update_service` — manage auxiliary services (Redis, Meilisearch, etc.)
- `list_service_presets` / `restore_service` / `delete_service_preset` — manage service presets
- `save_as_template` / `delete_template` / `list_templates` — template management
- `import_template_from_odoo` — import a template from a running Odoo instance via its database manager API
- `setup_repo_auth` — cache git credentials for private repositories
- `add_extra_repo` / `list_extra_repos` / `update_extra_repo` / `delete_extra_repo` — manage extra addons repositories
- `get_agent_instructions` — get AI agent skill with instructions on how to use Oduflow
- `get_odoo_development_guide` — get Odoo development standards guide for a specific version (15–19)

## Typical Agent Workflow

1. Call `list_environments` to check if an environment for the branch exists
2. If not, call `create_environment` with `branch_name`, `repo_url`, and `odoo_image`
3. Write code, `git push`, then call `pull_and_apply` (auto-detects what to do)
4. Use `install_odoo_modules` / `run_odoo_tests` / `get_environment_logs` to verify
5. Call `delete_environment` when the task is done

## Links

- Repository: <https://github.com/oduist/oduflow>
- License: Polyform Noncommercial 1.0.0
- Website: <https://oduflow.dev>
