# Moose / Local Dev Documentation – Python ## Included Files 1. moose/local-dev/local-dev.mdx ## Development Mode Source: moose/local-dev/local-dev.mdx Local development environment with hot reload and automatic infrastructure management # Setting Up Your Development Environment Development mode (`moose dev`) provides a full-featured local environment optimized for rapid iteration and debugging. It automatically manages Docker containers, provides hot reload capabilities, and includes enhanced debugging features. ## Getting Started ```bash # Start development environment moose dev # View your running infrastructure moose ls ``` ## Container Management Development mode automatically manages Docker containers for your infrastructure: - **ClickHouse** (when `olap` feature is enabled) - **Redpanda** (when `streaming_engine` feature is enabled) - **Temporal** (when `workflows` feature is enabled) - **Analytics APIs Server** (when `apis` feature is enabled) - **Redis** (always enabled) - **MCP Server** (always enabled) - Enables AI-assisted development. [Learn more](/moose/mcp-dev-server) ### Container Configuration Control which containers start with feature flags: ```toml copy # moose.config.toml [features] olap = true # Enables ClickHouse streaming_engine = true # Enables Redpanda workflows = false # Controls Temporal startup apis = true # Enables Analytics APIs server ``` ### Extending Docker Infrastructure You can extend Moose's Docker Compose configuration with custom services by creating a `docker-compose.dev.override.yaml` file in your project root. This allows you to add additional infrastructure (databases, monitoring tools, etc.) that runs alongside your Moose development environment. **Do not use docker-compose.dev.override.yaml to modify Moose-managed services** (ClickHouse, Redpanda, Redis, Temporal). The Docker Compose merge behavior makes it difficult to override existing configuration correctly, often leading to conflicts. Instead, use `moose.config.toml` to configure Moose infrastructure. See [Configuration](/moose/configuration) for all available options including database connections, ports, volumes, and service-specific settings. Use the override file **only for adding new services** that complement your Moose environment (e.g., PostgreSQL for application data, monitoring tools). **How it works:** When you run `moose dev`, Moose automatically detects and merges your override file with the generated Docker Compose configuration. The files are merged using Docker Compose's [standard merge behavior](https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/). **Example: Adding PostgreSQL for Application Data** Create a `docker-compose.dev.override.yaml` file in your project root: ```yaml copy filename="docker-compose.dev.override.yaml" services: postgres: image: postgres:16 environment: POSTGRES_USER: myapp POSTGRES_PASSWORD: mypassword POSTGRES_DB: myapp_db ports: - "5432:5432" volumes: - postgres-data:/var/lib/postgresql/data volumes: postgres-data: ``` Now when you run `moose dev`, PostgreSQL will start alongside your other infrastructure. You'll see a message confirming the override file is being used: ``` [moose] Using docker-compose.dev.override.yaml for custom infrastructure ``` **Recommended Use Cases:** - **Add databases**: PostgreSQL, MySQL, MongoDB for application data - **Add monitoring**: Grafana, Prometheus for metrics visualization - **Add custom services**: Additional message queues, caching layers, or development tools **Not Recommended:** - Modifying Moose-managed services (ClickHouse, Redpanda, Redis, Temporal) - Overriding ports, volumes, or environment variables for Moose infrastructure - Attempting to change database credentials or connection settings For any Moose infrastructure configuration, use `moose.config.toml` instead. See [Configuration](/moose/configuration). **Example: Adding Grafana for Monitoring** ```yaml copy filename="docker-compose.dev.override.yaml" services: grafana: image: grafana/grafana:latest ports: - "3001:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false volumes: - grafana-data:/var/lib/grafana volumes: grafana-data: ``` When merging files, Docker Compose follows these rules: - **Services**: Merged by name with values from the override file taking precedence - **Environment variables**: Appended (both files' values are used) - **Volumes**: Appended - **Ports**: Appended (use `!override` tag to replace instead of merge) See [Docker's merge documentation](https://docs.docker.com/reference/compose-file/merge/) for complete details. The override file is only used in development mode (`moose dev`). For production deployments, configure your infrastructure separately using your deployment platform's tools. ## Hot Reloading Development The development runtime includes a file watcher that provides near-instantaneous feedback when you save code changes. ### Watched Files The file watcher recursively monitors your entire `app/` directory structure and only rebuilds the components that actually changed. Only the root file in your `app/` directory is run when changes are detected. In order for your tables/streams/apis/workflows to be detected, you must import them in your root file (`main.py`). If you change a file in your app directory and it is a dependency of your root file, then those changes WILL be detected. ## Quick Example **❌ Doesn't work - No export from root:** ```py file="app/tables/users.py" from schemas.user import UserSchema users_table = OlapTable[UserSchema]("Users") # Moose can't see this - not imported in main.py ``` **✅ Works - Import in main file:** ```py file="app/tables/users.py" {3} from schemas.user import UserSchema users_table = OlapTable[UserSchema]("Users") # No export needed - Python modules are automatically discovered ``` ```py file="app/main.py" from tables.users import users_table # Moose sees this ``` Now because we imported the table in the main file, Moose will detect the change and rebuild the table. **✅ Works - Change dependency:** ```ts file="app/schemas/user.ts" {5} export interface UserSchema { id: string; name: string; email: string; age: number; // Adding this triggers migration } ``` *Moose detects this because `UserSchema` is imported in the root file via the dependency chain.* Learn more about how Moose handles migrations. ## Script Execution Hooks You can configure your dev server to run your own shell commands automatically during development. Use these hooks to keep generated artifacts in sync (e.g., refreshing external models, regenerating OpenAPI SDKs). ### Available hooks - `on_first_start_script`: runs once when the dev server first starts in this process - `on_reload_complete_script`: runs after each dev server reload when code/infra changes have been fully applied Configure these in `moose.config.toml` under the `http_server_config` section: ```toml copy # moose.config.toml [http_server_config] # One-time on first start on_first_start_script = "echo 'dev started'" # After every code/infra reload completes on_reload_complete_script = "echo 'reload complete'" ``` Notes: - Scripts run from your project root using your `$SHELL` (falls back to `/bin/sh`). - Use `&&` to chain multiple commands or point to a custom script. - Prefer passing credentials via environment variables or your secret manager. ### Use case: keep external models in sync (DB Pull) Refresh `EXTERNALLY_MANAGED` table models from a remote ClickHouse on dev start so your local code matches the live schema. ```bash filename="Terminal" copy export REMOTE_CLICKHOUSE_URL="https://username:password@host:8443/?database=default" ``` ```toml copy # moose.config.toml [http_server_config] on_first_start_script = "moose db pull --connection-string $REMOTE_CLICKHOUSE_URL" ``` See the full guide: [/moose/olap/db-pull](/moose/olap/db-pull) ### Use case: regenerate OpenAPI SDKs on reload Automatically regenerate client SDKs after Moose finishes applying code/infra changes so `.moose/openapi.yaml` is fresh. ```toml copy # moose.config.toml [http_server_config] on_first_start_script = "command -v openapi-generator-cli >/dev/null 2>&1 || npm i -g @openapitools/openapi-generator-cli" on_reload_complete_script = "openapi-generator-cli generate -i .moose/openapi.yaml -g typescript-fetch -o ./generated/ts" ``` More examples: [/moose/apis/openapi-sdk](/moose/apis/openapi-sdk) ## Local Infrastructure ### Port Allocation Development mode uses the following default ports: - **4000**: Main API server - **5001**: Management API (health checks, metrics, admin, OpenAPI docs) ### Service URLs Access your development services at: ```bash # Main application http://localhost:4000 # Management interface curl http://localhost:5001/metrics # OpenAPI documentation http://localhost:5001/openapi.yaml ``` ### Container Networking All containers run in an isolated Docker network with automatic service discovery: - Containers communicate using service names - Port mapping only for external access - Automatic DNS resolution between services ### MCP Server for AI-Assisted Development Development mode includes a built-in Model Context Protocol (MCP) server that lets AI assistants interact with your local infrastructure through natural language. **What you can do:** - Query your ClickHouse database with natural language - Inspect streaming topics and messages - Search and filter development logs - Explore your infrastructure map **Quick setup:** The MCP server runs automatically at `http://localhost:4000/mcp`. For Claude Code, just run: ```bash copy claude mcp add --transport http moose-dev http://localhost:4000/mcp ``` For other AI clients (Windsurf, VS Code, Cursor, Claude Desktop), see the [full setup guide](/moose/mcp-dev-server). **Example prompts:** - *"What errors are in the logs?"* - *"What tables exist in my project?"* - *"Show me the schema of all tables"* - *"Sample 5 messages from the Foo stream"* See the complete guide for all available tools, detailed configuration for each AI client, and example workflows. ## Troubleshooting ### Common Issues **Container Startup Failures** ```bash # Check Docker is running docker info # View container logs moose logs ``` **Port Conflicts** ```bash # Check what's using your ports lsof -i :4000 lsof -i :5001 # Use custom ports export MOOSE_HTTP_PORT=4040 export MOOSE_MANAGEMENT_PORT=5010 moose dev ```