<!--
hoody-daemon Subskill (http)
Auto-generated by Hoody Skills Generator
Generated: 2026-06-20T00:42:42.768Z
Model: mimo-v2.5-pro + fixer:mimo-v2.5-pro
Mode: http


Tokens: 8216

DO NOT EDIT MANUALLY - Changes will be overwritten on next generation
-->

# hoody-daemon Subskill

## Overview

**Service**: hoody-daemon — Long-running service management via HTTP

**Purpose**: Manages daemon programs (long-running processes) through supervisord. Start, stop, monitor, and configure processes programmatically. Supports persistent programs and ephemeral "quick-start" tasks.

**When to use**:
- Running custom background workers, queues, or servers
- Managing port-range programs for dynamic scaling
- Temporary task execution with automatic cleanup
- Process health monitoring and log retrieval

**Hoody Philosophy Fit**: hoody-daemon exemplifies service management abstraction. Instead of SSH + supervisord CLI, agents interact via HTTP. Programs survive container restarts (persistent) or auto-clean (ephemeral). Configuration is declarative JSON, not imperative scripts.

**Base URL Pattern** (Hoody Kit service):
```
https://{projectId}-{containerId}-daemon-{serviceId}.{node}.containers.hoody.com
```

**Key Concepts**:
- **Programs**: Persistent daemon configurations stored in `programs.json`. Survive reboots.
- **Quick-Start**: Ephemeral programs auto-cleaned on stop or reboot. For one-off tasks.
- **Port-Range Programs**: Programs with multiple instances across port ranges.
- **supervisord Integration**: All programs backed by supervisord process management.

**Service Discovery**: Obtain the daemon base URL via container metadata or the Hoody API. See core SKILL.md for container creation and service discovery patterns.

---

## Common Workflows

### 1. Health Check

Verify the daemon service is running and responsive.

```
curl -s \
  "${BASE_URL}/api/v1/daemon/health"
```

**Response**:
```
{
  "status": "ok",
  "service": "hoody-daemon",
  "timestamp": "2025-01-15T10:30:00Z",
  "version": "1.0.0",
  "uptime": 86400,
  "checks": {
    "supervisord": "connected"
  }
}
```

**Notes**: Unauthenticated endpoint. Always returns HTTP 200 when service is up.

---

### 2. List All Programs

Retrieve all configured daemon programs with optional filters.

```
# List all programs
curl -s \
  "${BASE_URL}/api/v1/daemon/programs"

# Filter by enabled status
curl -s \
  "${BASE_URL}/api/v1/daemon/programs?enabled=true"

# Filter by hoody_kit programs
curl -s \
  "${BASE_URL}/api/v1/daemon/programs?hoody_kit=true"
```

**Response**:
```
[
  {
    "id": "worker-abc123",
    "name": "my-worker",
    "command": "node /app/worker.js",
    "user": "app",
    "enabled": true,
    "hoody_kit": false,
    "port_range": {
      "start": 3000,
      "end": 3000
    }
  }
]
```

---

### 3. Add a New Program

Create a custom daemon program. Requires all fields below.

```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/add" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-queue-worker",
    "command": "node /app/workers/queue-processor.js --concurrency=5",
    "user": "app",
    "port_range": {
      "start": 4000,
      "end": 4000
    }
  }'
```

**Response**:
```
{
  "id": "queue-worker-xyz789",
  "name": "my-queue-worker",
  "command": "node /app/workers/queue-processor.js --concurrency=5",
  "user": "app",
  "enabled": true,
  "port_range": {
    "start": 4000,
    "end": 4000
  }
}
```

**Verify**: Check status after adding:

```
curl -s \
  "${BASE_URL}/api/v1/daemon/status/queue-worker-xyz789"
```

---

### 4. Edit an Existing Program

Update program configuration. Only provided fields are updated; others retain current values.

```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/edit/queue-worker-xyz789" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-queue-worker",
    "command": "node /app/workers/queue-processor.js --concurrency=10",
    "user": "app",
    "port_range": {
      "start": 4000,
      "end": 4000
    }
  }'
```

**Notes**: Program must be stopped before editing if the command changes.

---

### 5. Start and Stop Programs

Control program execution via supervisorctl.

```
# Start a program
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/queue-worker-xyz789/start"

# Stop a program
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/queue-worker-xyz789/stop"

# Start with wait (blocks until RUNNING state)
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/queue-worker-xyz789/start?wait=true"
```

**Response**:
```
{
  "id": "queue-worker-xyz789",
  "status": "running",
  "pid": 12345
}
```

---

### 6. Enable and Disable Programs

Enable registers with supervisord; disable removes from supervisord config.

```
# Enable a program (registers with supervisord)
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/queue-worker-xyz789/enable"

# Disable a program (removes from supervisord, stops if running)
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/queue-worker-xyz789/disable"
```

**Difference from start/stop**: Enable/disable controls boot-time registration. Start/stop controls immediate execution.

---

### 7. View Program Logs

Retrieve recent log output from stdout or stderr.

```
# Get last 100 lines (default)
curl -s \
  "${BASE_URL}/api/v1/daemon/programs/queue-worker-xyz789/logs"

# Get last 50 lines of stderr
curl -s \
  "${BASE_URL}/api/v1/daemon/programs/queue-worker-xyz789/logs?lines=50&stream=stderr"
```

**Response**:
```
{
  "id": "queue-worker-xyz789",
  "stream": "stdout",
  "lines": 100,
  "log": "2025-01-15T10:30:00 Processing job 123\n2025-01-15T10:30:01 Job 123 complete\n"
}
```

---

### 8. Quick-Start (Ephemeral Programs)

Create temporary programs that auto-clean on stop or container reboot.

```
# Start an ephemeral task
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/quick-start" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "node /app/scripts/migrate.js --target=v2",
    "user": "app"
  }'
```

**Response**:
```
{
  "id": "ephemeral-qrs456",
  "command": "node /app/scripts/migrate.js --target=v2",
  "user": "app",
  "status": "running"
}
```

**Check status**:
```
curl -s \
  "${BASE_URL}/api/v1/daemon/quick-start/ephemeral-qrs456/status"
```

**Stop and cleanup** (removes supervisord config and tracking):
```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/quick-start/ephemeral-qrs456/stop"
```

**View logs**:
```
curl -s \
  "${BASE_URL}/api/v1/daemon/quick-start/ephemeral-qrs456/logs"
```

---

### 9. Remove a Program

Permanently deletes a program. Stops it first if running.

```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/remove/queue-worker-xyz789"
```

**Response**:
```
{
  "removed": "queue-worker-xyz789"
}
```

**⚠️ Destructive**: Cannot be undone. Configuration is permanently deleted.

---

### 10. Reset to Defaults

Replace all programs with the initial default snapshot from container setup.

```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/reset"
```

**Actions**:
1. Stops all managed programs
2. Removes supervisord configs
3. Re-applies `programs.default.json`

**Use case**: Recover from broken configuration; restore factory state.

---

## Advanced Operations

### 11. Multi-Program Deployment Workflow

Deploy multiple related services in sequence with verification.

**Step 1**: Check current state
```
curl -s \
  "${BASE_URL}/api/v1/daemon/programs"
```

**Step 2**: Add programs
```
# Add API server
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/add" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "api-server",
    "command": "node /app/server.js --port=3000",
    "user": "app",
    "port_range": {
      "start": 3000,
      "end": 3000
    }
  }'

# Add background worker
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/add" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "bg-worker",
    "command": "node /app/worker.js --queue=default",
    "user": "app",
    "port_range": {
      "start": 3001,
      "end": 3001
    }
  }'
```

**Step 3**: Start all and verify
```
# Start API server with wait
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/api-server/start?wait=true"

# Start worker
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/bg-worker/start"

# Verify all statuses
curl -s \
  "${BASE_URL}/api/v1/daemon/status"
```

---

### 12. Port-Range Program Management

Programs with port ranges spawn multiple instances (e.g., load-balanced workers).

```
# Add port-range program
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/add" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "web-pool",
    "command": "node /app/server.js",
    "user": "app",
    "port_range": {
      "start": 3000,
      "end": 3009
    }
  }'

# Start specific instance on port 3005
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/web-pool/start?port=3005"

# Stop specific instance
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/web-pool/stop?port=3005"

# Stop all instances
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/web-pool/stop?all=true"

# View all running instances
curl -s \
  "${BASE_URL}/api/v1/daemon/status/web-pool"
```

---

### 13. Program Update Workflow

Safe update pattern: stop → edit → start → verify.

```
PROGRAM_ID="queue-worker-xyz789"

# Step 1: Stop the program
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/${PROGRAM_ID}/stop"

# Step 2: Verify stopped
curl -s \
  "${BASE_URL}/api/v1/daemon/status/${PROGRAM_ID}"

# Step 3: Edit configuration
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/edit/${PROGRAM_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "queue-worker",
    "command": "node /app/workers/queue-v2.js --concurrency=20",
    "user": "app",
    "port_range": {
      "start": 4000,
      "end": 4000
    }
  }'

# Step 4: Start with wait
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/${PROGRAM_ID}/start?wait=true"

# Step 5: Check logs for errors
curl -s \
  "${BASE_URL}/api/v1/daemon/programs/${PROGRAM_ID}/logs?lines=20&stream=stderr"
```

---

### 14. Quick-Start for Data Migrations

Run one-off migrations with log capture and cleanup.

```
# Start migration
RESPONSE=$(curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/quick-start" \
  -H "Content-Type: application/json" \
  -d '{
    "command": "node /app/scripts/migrate.js --target=v3 --dry-run=false",
    "user": "app"
  }')

# Extract ID (using jq)
TASK_ID=$(echo "$RESPONSE" | jq -r '.id')

# Monitor logs
curl -s \
  "${BASE_URL}/api/v1/daemon/quick-start/${TASK_ID}/logs"

# Check status
curl -s \
  "${BASE_URL}/api/v1/daemon/quick-start/${TASK_ID}/status"

# Cleanup when done
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/quick-start/${TASK_ID}/stop"
```

---

### 15. Error Recovery: Reset and Redeploy

When configuration is corrupted or programs are in bad state.

**Step 1**: Reset to defaults
```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/reset"
```

**Step 2**: Verify clean state
```
curl -s \
  "${BASE_URL}/api/v1/daemon/programs"
```

**Step 3**: Re-add custom programs
```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/add" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-worker",
    "command": "node /app/worker.js",
    "user": "app",
    "port_range": {
      "start": 3000,
      "end": 3000
    }
  }'
```

**Step 4**: Enable and start
```
curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/my-worker/enable"

curl -s -X POST \
  "${BASE_URL}/api/v1/daemon/programs/my-worker/start?wait=true"
```

---

### 16. Performance Considerations

- **Wait parameter**: Use `?wait=true` only when you need to confirm program reached RUNNING state. Otherwise, start is non-blocking.
- **Log retrieval**: Default is 100 lines. Use `?lines=N` to limit payload size for large logs.
- **Port ranges**: Max range is 1000 ports. Spawning 1000 instances is allowed but resource-intensive.
- **Quick-start cleanup**: Ephemeral programs auto-clean on reboot, but explicit stop ensures immediate resource release.
- **Bulk operations**: No batch endpoint exists. Use sequential calls for multiple programs.

---

## Quick Reference



### Required Fields Summary

**programs/add & programs/edit/{id}**: `name`, `command`, `user`, `port_range` (object with `start`, `end`)

**quick-start**: `command`, `user`



### Typical Workflow States

```
Disabled → Enabled → Stopped → Running → Stopped
                                  ↓
                            (Quick-start)
                                  ↓
                              Removed
```