Development setup guide for Shelly Manager, covering backend (Core/API/CLI) and web development.
- Docker & Docker Compose (recommended)
- Python 3.11+ and uv (for local development)
- Node.js 20+ (for web development)
# Clone repository
git clone https://github.com/jfmlima/shelly-manager.git
cd shelly-manager
# The api and cli services require this. Put it in a .env file to keep it.
export SHELLY_SECRET_KEY=$(openssl rand -base64 32 | tr '+/' '-_')
# Start development environment
docker compose up -d
# Access services:
# - API: http://localhost:8000
# - Web UI: http://localhost:5173
# - API Docs: http://localhost:8000/docsThe CLI ships as an opt-in profile, so docker compose up -d does not start it. Its entrypoint keeps the container idle, which means you drive it with exec rather than run:
docker compose --profile cli up -d cli
docker compose exec cli shelly-manager scan 192.168.1.0/24
docker compose down clidown cli names the service, so it removes only that container. Neither other form does what you might expect: a bare docker compose down tears down the default-profile services and leaves cli running, and because cli sets restart: unless-stopped it then survives reboots unnoticed. docker compose --profile cli down is the one that takes everything.
Both source trees are bind-mounted into that container, so edits on the host take effect without a rebuild.
The api service keeps its database and firmware cache in a named volume mounted at /data, so a plain down leaves both in place. docker compose down -v removes the volume too, which is how you get back to an empty database.
-
Install uv:
curl -LsSf https://astral.sh/uv/install.sh | sh # or pip install uv
-
Install dependencies:
# Install all workspace packages with dev dependencies uv sync --extra dev -
Test everything works:
# Test all packages make test # Test specific packages make test-core make test-api make test-cli
Shelly Manager follows Clean Architecture principles with three main backend packages:
packages/
├── core/ # 🏛️ Business logic, domain models, use cases
├── api/ # 🌐 HTTP REST API (Litestar framework)
└── cli/ # 💻 Command-line interface (Click framework)
The project uses uv for workspace dependencies and consistent version management:
# Install all packages with dev dependencies
uv sync --extra dev
# Install without dev dependencies (production)
uv sync --no-dev
# Install specific package only
uv sync --package shelly-manager-core
uv sync --package shelly-manager-api
uv sync --package shelly-manager-cliCommands that read or write stored credentials or backups need SHELLY_SECRET_KEY in the environment, the same value the compose stack uses. Everything else, including --help and scan, runs without it.
# CLI tool
uv run --package shelly-manager-cli shelly-manager --help
uv run --package shelly-manager-cli shelly-manager scan 192.168.1.0/24
# API server, which unlike the CLI needs SHELLY_SECRET_KEY set
uv run --package shelly-manager-api python -m api.main
# Visit: http://localhost:8000/docs
# Core library testing
uv run --package shelly-manager-core python -c "
from core.domain.entities.shelly_device import ShellyDevice
print('✅ Core package working!')
"# Format code (black, ruff)
make format
# Check linting (ruff, mypy)
make lint
# Run all quality checks
make check# Run all backend tests
make test
# Test specific packages
make test-core
make test-api
make test-cli
# Run with coverage
make test-coverage
# Run specific test files
uv run --package shelly-manager-core pytest packages/core/tests/unit/
uv run --package shelly-manager-api pytest packages/api/tests/ -v- Domain-Driven Design: Business logic in
core/domain/ - Clean Architecture: Dependencies point inward to domain
- Dependency Injection: Use containers for external dependencies
- Async/Await: Async operations for network calls
- Type Safety: Comprehensive type hints with mypy
# Domain entities
packages/core/src/core/domain/entities/
# Use cases (application logic)
packages/core/src/core/use_cases/
# Gateways (external interfaces)
packages/core/src/core/gateways/# Controllers (HTTP handlers)
packages/api/src/api/controllers/
# DTOs (request/response models)
packages/api/src/api/presentation/dto/# Command groups
packages/cli/src/cli/commands/
# Use cases (CLI-specific logic)
packages/cli/src/cli/use_cases/The web interface is built with React, TypeScript, and modern tooling:
- Frontend: React 18 + TypeScript
- Build Tool: Vite
- UI Framework: shadcn/ui + Tailwind CSS
- State Management: TanStack Query (React Query v5)
- Forms: React Hook Form + Zod validation
- Tables: TanStack Table
# Navigate to web package
cd packages/web
# Install dependencies
npm install
# Start development server
npm run dev
# Visit: http://localhost:5173
# Build for production
npm run build
# Preview production build
npm run previewcd packages/web
# Lint TypeScript/React code
npm run lint
# Check TypeScript types
npm run type-check
# Format code (Prettier)
npm run format
# Check formatting
npm run format:check# Copy environment template
cp packages/web/env.example packages/web/.env.local
# Configure API endpoint
echo "VITE_BASE_API_URL=http://localhost:8000" > packages/web/.env.local# UI components
packages/web/src/components/ui/
# Feature components
packages/web/src/components/dashboard/
packages/web/src/components/device-detail/
# Layout components
packages/web/src/components/layout/# Page components
packages/web/src/pages/
# Add routes in
packages/web/src/App.tsx# API client and utilities
packages/web/src/lib/api.ts
# Type definitions
packages/web/src/types/api.ts- Functional Components: Use hooks exclusively
- Performance: Memoize expensive operations with
useMemo/useCallback - Error Boundaries: Wrap components for error handling
- Custom Hooks: Extract reusable logic
- Server State: TanStack Query for API data
- Component State: React
useState/useReducer - URL State: React Router for navigation state
- Local Storage: Custom hooks for persistence
- Strict TypeScript: No
anytypes - API Types: Shared type definitions with backend
- Form Validation: Zod schemas for runtime validation
# 1. Fork and clone the repository
git clone https://github.com/your-username/shelly-manager.git
cd shelly-manager
# 2. Create a feature branch
git checkout -b feature/amazing-feature
# 3. Make your changes and commit
git add .
git commit -m "feat: add amazing feature"
# 4. Push and create a pull request
git push origin feature/amazing-feature- Python: Follow PEP 8, use
blackandruff - TypeScript: Follow Airbnb style guide, use Prettier
- Commits: Use conventional commits (feat:, fix:, docs:, etc.)
- Unit Tests: Cover all new business logic
- Integration Tests: Test API endpoints and CLI commands
- Type Safety: Ensure all code passes mypy/TypeScript checks
- Code Documentation: Use docstrings and JSDoc comments
- README Updates: Update relevant package READMEs
- API Documentation: Update OpenAPI specs for API changes
# Quality and Testing
make lint # Run all linting (black, ruff, mypy)
make format # Format all code (black, ruff)
make test # Run all tests (backend + web)
make test-coverage # Run tests with coverage reports
# Package-specific commands
make test-core # Test core package only
make test-api # Test API package only
make test-cli # Test CLI package only
make test-web # Test web package only
# Development
make install # Install all packages
make install-dev # Install with dev dependencies
make clean # Clean build artifacts
make run-api # Start API server locally
# Docker development
docker compose up -d # Start development stack
docker compose down # Stop the default services (leaves the cli profile)Pre-commit hooks ensure code quality before commits:
# Install pre-commit hooks (one-time setup)
pre-commit install
# Run hooks manually
pre-commit run --all-files
# Skip hooks (not recommended)
git commit --no-verifyThe hooks automatically:
- Format code with black
- Run linting with ruff
- Check type safety with mypy/TypeScript
- Run tests on affected packages
- Check YAML/JSON syntax
# Debug API server with breakpoints
uv run --package shelly-manager-api python -m debugpy --listen 5678 -m api.main
# Debug CLI commands
uv run --package shelly-manager-cli python -m debugpy --listen 5679 -m cli.__main__ scan --help
# Test individual components
uv run --package shelly-manager-core python -c "
import asyncio
from core.use_cases.scan_devices import ScanDevicesUseCase
# Add your debug code here
"cd packages/web
# Start with debug logging
DEBUG=true npm run dev
# Build analysis
npm run build -- --analyze
# TypeScript debugging
npx tsc --noEmit --incremental- Docker volume permissions: Use
:ro(read-only) mounts for source code - Port conflicts: Check if ports 8000, 5173 are already in use
- uv sync issues: Clear cache with
uv cache clean - Node modules: Clear with
rm -rf node_modules && npm install
- Architecture Documentation: See
packages/core/README.md - API Documentation: Visit
http://localhost:8000/docswhen API is running - CLI Documentation: See
packages/cli/README.md - Web UI Documentation: See
packages/web/README.md - Testing Documentation: See
packages/cli/tests/README.md
- Documentation Issues: Check package-specific READMEs first
- Bug Reports: Open an issue with reproduction steps
- Feature Ideas: Start a discussion to validate the idea
- Development Questions: Check existing issues or start a discussion