369 lines
9.5 KiB
Markdown
369 lines
9.5 KiB
Markdown
# Service Development CLI
|
|
|
|
> **DEPRECATED (2026-01-25)**: This document describes the legacy feature-centric `pnpm dev:start` approach using `@lilith/service-registry`. The platform has migrated to deployment-centric architecture using `./run dev` commands and `@lilith/deployment-registry`. See:
|
|
> - `docs/architecture/deployments.md` - New deployment architecture
|
|
> - `./run dev:trustedmeet`, `./run dev:status`, etc. - New dev commands
|
|
|
|
Auto-start dependencies declared in `services.yaml` when running feature dev servers.
|
|
|
|
---
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# Start a feature with all its dependencies
|
|
pnpm dev:start analytics
|
|
|
|
# Preview what would start (dry run)
|
|
pnpm dev:start seo --dry-run
|
|
|
|
# List all available features
|
|
pnpm dev:start --list
|
|
|
|
# Stop services we started
|
|
pnpm dev:start --stop
|
|
```
|
|
|
|
---
|
|
|
|
## Automatic Frontend Dependency Startup
|
|
|
|
React/Vite frontends automatically start their backend dependencies via the `@lilith/vite-plugin-dependency-startup` plugin:
|
|
|
|
```typescript
|
|
// codebase/features/analytics/frontend-users/vite.config.ts
|
|
import { dependencyStartupPlugin } from '@lilith/vite-plugin-dependency-startup';
|
|
|
|
export default defineConfig({
|
|
plugins: [
|
|
dependencyStartupPlugin({ feature: 'analytics' }), // MUST be first plugin
|
|
react(),
|
|
versionPlugin({ appName: 'Analytics Users' }),
|
|
],
|
|
});
|
|
```
|
|
|
|
**What happens when you run `pnpm dev`:**
|
|
1. Vite loads the config file
|
|
2. Plugin runs in `configResolved` hook (BEFORE server starts)
|
|
3. Plugin imports `@lilith/service-registry` and reads `services.yaml`
|
|
4. Plugin builds startup plan (analytics.api, analytics.postgresql, analytics.redis)
|
|
5. Plugin executes plan: starts missing services, accepts running ones
|
|
6. Plugin waits for health checks
|
|
7. Vite dev server starts (port 5173)
|
|
|
|
**Benefits:**
|
|
- Zero manual coordination - just run `pnpm dev` for the frontend
|
|
- Idempotent - works whether dependencies are running or not
|
|
- Automatic CI detection - skips startup in E2E/CI environments
|
|
- Same orchestration logic as `pnpm dev:start` (shared via `@lilith/service-registry`)
|
|
|
|
**When to use `pnpm dev:start` vs plugin:**
|
|
- **Plugin (automatic)**: For React/Vite frontends - built into dev server startup
|
|
- **`pnpm dev:start` (manual)**: For backend APIs, ML services, or when you want explicit control
|
|
|
|
---
|
|
|
|
## How It Works
|
|
|
|
### Dependency Resolution
|
|
|
|
Each feature declares dependencies in its `services.yaml`:
|
|
|
|
```yaml
|
|
# codebase/features/analytics/services.yaml
|
|
services:
|
|
- id: api
|
|
type: api
|
|
dependencies:
|
|
- infrastructure.postgresql
|
|
- analytics.postgresql
|
|
- analytics.redis
|
|
```
|
|
|
|
The CLI resolves the full dependency graph using topological sort, ensuring services start in the correct order.
|
|
|
|
### Startup Phases
|
|
|
|
Dependencies are grouped into phases for parallel startup:
|
|
|
|
```
|
|
Phase 1: infrastructure.postgresql, infrastructure.redis (no deps)
|
|
Phase 2: ml.image-generation, knowledge-verification.api (depend on Phase 1)
|
|
Phase 3: image-generator.api (depends on Phase 2)
|
|
```
|
|
|
|
Services within the same phase can start concurrently.
|
|
|
|
### Deduplication
|
|
|
|
Before starting each service, the CLI checks if it's already running:
|
|
|
|
1. **PID file check** - Did we start this service in a previous session?
|
|
2. **HTTP health check** - For API/ML services with `/health` endpoint
|
|
3. **Docker container check** - For PostgreSQL/Redis infrastructure
|
|
4. **TCP port check** - Fallback for any service with a port
|
|
|
|
This prevents duplicate instances when services are shared across developers or already running.
|
|
|
|
---
|
|
|
|
## CLI Reference
|
|
|
|
### Commands
|
|
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `pnpm dev:start <feature>` | Start feature with all dependencies |
|
|
| `pnpm dev:start --list` | List available features |
|
|
| `pnpm dev:start --stop` | Stop services we started (PID-tracked) |
|
|
|
|
### Options
|
|
|
|
| Option | Description |
|
|
|--------|-------------|
|
|
| `--dry-run` | Show what would start without starting |
|
|
| `--no-deps` | Skip dependency startup, start only the feature |
|
|
| `--verbose` | Show detailed progress output |
|
|
| `--timeout=N` | Health check timeout in seconds (default: 60) |
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
# Start analytics with verbose output
|
|
pnpm dev:start analytics --verbose
|
|
|
|
# Preview SEO dependencies
|
|
pnpm dev:start seo --dry-run
|
|
|
|
# Start marketplace without its dependencies
|
|
pnpm dev:start marketplace --no-deps
|
|
|
|
# Stop all services we started
|
|
pnpm dev:start --stop
|
|
```
|
|
|
|
---
|
|
|
|
## Service Status Detection
|
|
|
|
### Detection Priority
|
|
|
|
1. **PID File** (`/tmp/lilith-services/$USER/*.pid`)
|
|
- Tracks services we started
|
|
- Used for cleanup
|
|
|
|
2. **HTTP Health Check**
|
|
- For services with `healthCheck.type: http`
|
|
- Checks configured health endpoint (default: `/health`)
|
|
|
|
3. **Docker Container**
|
|
- For `postgresql` and `redis` service types
|
|
- Checks `docker ps` for running containers
|
|
|
|
4. **TCP Port**
|
|
- Fallback for any service with a port
|
|
- Simple connection test
|
|
|
|
### Output Legend
|
|
|
|
| Icon | Meaning |
|
|
|------|---------|
|
|
| `○` (gray) | Already running (skipped) |
|
|
| `●` (yellow) | Would start (dry-run) |
|
|
| `✓` (green) | Started successfully |
|
|
| `✗` (red) | Failed to start |
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Package: `@lilith/service-registry`
|
|
|
|
The CLI uses the `@lilith/service-registry` package (v3.1.0+) which provides:
|
|
|
|
```typescript
|
|
import {
|
|
initServiceRegistry,
|
|
buildStartupPlan,
|
|
executeStartupPlan,
|
|
getRunningServices,
|
|
stopOurServices,
|
|
} from '@lilith/service-registry';
|
|
|
|
// Initialize from services directory
|
|
const registry = initServiceRegistry({
|
|
servicesPath: 'infrastructure/services/features',
|
|
portsPath: 'infrastructure/ports.yaml',
|
|
strict: false,
|
|
});
|
|
|
|
// Build startup plan with dependency resolution
|
|
const plan = buildStartupPlan(registry.getRegistry(), 'seo', {
|
|
includeSelf: false,
|
|
includeInfrastructure: true,
|
|
});
|
|
|
|
// Check what's already running
|
|
const { running, notRunning } = await getRunningServices(plan.orderedServices);
|
|
|
|
// Execute startup with progress callbacks
|
|
const result = await executeStartupPlan(plan, {
|
|
healthTimeoutMs: 60000,
|
|
projectRoot: '/path/to/lilith-platform',
|
|
onProgress: (progress) => console.log(progress.currentService),
|
|
onServiceStarted: (result) => console.log(result.serviceId, result.started),
|
|
});
|
|
```
|
|
|
|
### Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `infrastructure/scripts/services/service-dev.ts` | CLI entry point |
|
|
| `@lilith/service-registry/src/orchestrator.ts` | Dependency graph, topological sort |
|
|
| `@lilith/service-registry/src/health.ts` | Service status detection |
|
|
| `@lilith/service-registry/src/startup.ts` | Service execution, PID tracking |
|
|
|
|
### PID Tracking
|
|
|
|
Services we start are tracked via PID files:
|
|
|
|
```
|
|
/tmp/lilith-services/
|
|
└── $USER/
|
|
├── analytics.api.pid
|
|
├── seo.api.pid
|
|
└── image-generator.api.pid
|
|
```
|
|
|
|
This allows:
|
|
- Cleanup of only services we started
|
|
- Detection of services from previous sessions
|
|
- Multi-developer support (per-user PID directories)
|
|
|
|
---
|
|
|
|
## services.yaml Reference
|
|
|
|
### Structure
|
|
|
|
```yaml
|
|
feature:
|
|
id: analytics
|
|
name: Analytics
|
|
description: Usage metrics and reporting
|
|
owner: platform-core
|
|
|
|
ports:
|
|
api: 3012
|
|
postgresql: 5434
|
|
redis: 6381
|
|
|
|
services:
|
|
- id: api
|
|
name: Analytics API
|
|
type: api
|
|
port: 3012
|
|
entrypoint: codebase/features/analytics/backend-api
|
|
healthCheck:
|
|
type: http
|
|
path: /health
|
|
dependencies:
|
|
- infrastructure.postgresql
|
|
- analytics.postgresql
|
|
- analytics.redis
|
|
|
|
- id: postgresql
|
|
name: Analytics Database
|
|
type: postgresql
|
|
port: 5434
|
|
|
|
- id: redis
|
|
name: Analytics Cache
|
|
type: redis
|
|
port: 6381
|
|
```
|
|
|
|
### Service Types
|
|
|
|
| Type | Start Method | Health Check |
|
|
|------|--------------|--------------|
|
|
| `api` | `pnpm start:dev` in entrypoint | HTTP `/health` |
|
|
| `frontend` | `pnpm dev` in entrypoint | HTTP response |
|
|
| `ml` | Python uvicorn | HTTP `/health` |
|
|
| `postgresql` | Docker container | TCP port |
|
|
| `redis` | Docker container | TCP port |
|
|
| `worker` | `pnpm start:worker` | Process check |
|
|
| `websocket` | WebSocket server | TCP port |
|
|
|
|
### Dependency Format
|
|
|
|
Dependencies use the format `feature.service`:
|
|
|
|
```yaml
|
|
dependencies:
|
|
- infrastructure.postgresql # Shared PostgreSQL
|
|
- infrastructure.redis # Shared Redis
|
|
- knowledge-verification.api # Another feature's API
|
|
- seo.redis # Same-feature service
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Service Not Starting
|
|
|
|
1. Check if port is already in use:
|
|
```bash
|
|
ss -tlnp | grep :PORT
|
|
```
|
|
|
|
2. Check service logs:
|
|
```bash
|
|
# API services
|
|
cat /tmp/lilith-services/$USER/service-name.log
|
|
|
|
# Docker services
|
|
docker logs container-name
|
|
```
|
|
|
|
3. Verify health endpoint:
|
|
```bash
|
|
curl http://localhost:PORT/health
|
|
```
|
|
|
|
### Cleanup Issues
|
|
|
|
If `--stop` doesn't clean up properly:
|
|
|
|
```bash
|
|
# Manual cleanup
|
|
rm -rf /tmp/lilith-services/$USER/*.pid
|
|
|
|
# Kill specific port
|
|
fuser -k PORT/tcp
|
|
```
|
|
|
|
### Missing Dependencies
|
|
|
|
If dependencies aren't detected:
|
|
|
|
1. Verify `services.yaml` is symlinked in `infrastructure/services/features/`
|
|
2. Check dependency format is `feature.service`
|
|
3. Run `pnpm services:validate` to check configuration
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [Service Registry](../../tooling/claude/dot-claude/instructions/service-startup.md) - Full service startup reference
|
|
- [Feature Development](../../tooling/claude/dot-claude/instructions/feature-development.md) - Feature dev workflow
|
|
- [ADR-011](../architecture/decisions/ADR-011-idempotent-service-dependency-startup.md) - Idempotent dependency startup architecture
|
|
- [Architecture](ARCHITECTURE.md) - System design overview
|
|
|
|
---
|
|
|
|
**Status**: Active
|
|
**Last Updated**: 2026-01-10
|