<!--
hoody-cron Subskill (sdk)
Auto-generated by Hoody Skills Generator
Generated: 2026-05-06T20:05:42.920Z
Model: mimo-v2.5-pro
Mode: sdk


Tokens: 5321

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

# hoody-cron Subskill

## Overview

**hoody-cron** provides managed cron job scheduling for Hoody container services. It enables you to create, schedule, enable/disable, and auto-expire recurring tasks within your Hoody project containers.

### When to Use hoody-cron

- Schedule recurring maintenance tasks (cleanup, backups, health checks)
- Run periodic data processing jobs
- Automate report generation
- Manage time-based workflows that need enable/disable control
- Set tasks with automatic expiration dates

### Service Philosophy

hoody-cron follows Hoody's managed service approach: you define *what* to run and *when*, and the service handles execution, monitoring, and lifecycle management. Jobs are user-scoped, allowing multi-tenant isolation within a single project.

### Architecture

- **Crontab**: Raw cron expression configuration per user
- **Entries**: Individual managed cron jobs with metadata, scheduling, and lifecycle control
- **Auto-expiration**: Jobs can be configured to automatically disable after a set time

### Service URL Pattern

```
https://{projectId}-{containerId}-cron-{serviceId}.{node}.containers.hoody.icu
```

> **Note**: The SDK handles URL construction automatically. You only need to configure the base URL when initializing the client.

---

## Common Workflows

### Workflow 1: Create a Scheduled Job

Create a new cron entry that runs a command on a schedule.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({
  baseURL: 'https://api.hoody.icu',
  token: 'YOUR_TOKEN'
})

// Create a new cron entry
const entry = await client.cron.entries.create('my-user', {
  command: '/usr/bin/backup.sh',
  schedule: '0 2 * * *'  // Daily at 2:00 AM
})

console.log('Created entry:', entry.id)
```

**Verify creation:**

```
const retrieved = await client.cron.entries.get('my-user', entry.id)
console.log('Entry status:', retrieved)
```

### Workflow 2: List All Entries for a User

Retrieve all cron entries for a specific user.

```
// Simple list with pagination
const entries = await client.cron.entries.list('my-user', 1, 50)
console.log('Total entries:', entries)
```

**Collect all pages automatically:**

```
const allEntries = await client.cron.entries.listAll({ user: 'my-user' })
console.log('All entries collected:', allEntries.length)
```

**Use async iterator for large datasets:**

```
const iterator = client.cron.entries.listIterator({ user: 'my-user' })

for await (const batch of iterator) {
  console.log('Processing batch:', batch)
}
```

### Workflow 3: Update an Existing Entry

Modify the schedule or command of an existing cron entry.

```
// First, get the entry to confirm it exists
const existing = await client.cron.entries.get({ user: 'my-user', id: 'entry-id-123' })

// Update the entry
const updated = await client.cron.entries.update('my-user', 'entry-id-123', {
  schedule: '0 4 * * *'  // Change to 4:00 AM
})

console.log('Updated entry:', updated)
```

### Workflow 4: Delete a Cron Entry

Remove a cron entry that is no longer needed.

```
// Verify entry exists before deletion
const entry = await client.cron.entries.get({ user: 'my-user', id: 'entry-id-123' })

// Delete the entry
const result = await client.cron.entries.delete({ user: 'my-user', id: 'entry-id-123' })
console.log('Deletion result:', result)
```

### Workflow 5: Manage Raw Crontab

Work with the raw crontab configuration for a user.

```
// Get current crontab for a user
const crontab = await client.cron.crontab.get({ user: 'my-user' })
console.log('Current crontab:', crontab)
```

**Replace the entire crontab:**

```
const updated = await client.cron.crontab.put('my-user', {
  crontab: '0 2 * * * /usr/bin/backup.sh\n0 6 * * 1 /usr/bin/report.sh'
})

console.log('Crontab updated:', updated)
```

### Workflow 6: List All Crontabs Globally

View all crontabs across all users (admin operation).

```
// Simple list
const crontabs = await client.cron.crontab.listGlobal(1, 100)
console.log('Global crontabs:', crontabs)
```

**Collect all pages:**

```
const allCrontabs = await client.cron.crontab.listGlobalAll()
console.log('Total crontabs:', allCrontabs.length)
```

---

## Advanced Operations

### Multi-Step: Create and Verify a Scheduled Pipeline

Set up a multi-job pipeline with dependencies.

```
const userId = 'pipeline-user'

// Step 1: Create data extraction job
const extractJob = await client.cron.entries.create(userId, {
  command: '/scripts/extract-data.sh',
  schedule: '0 1 * * *'  // 1:00 AM daily
})

// Step 2: Create transformation job (runs after extraction)
const transformJob = await client.cron.entries.create(userId, {
  command: '/scripts/transform-data.sh',
  schedule: '30 1 * * *'  // 1:30 AM daily
})

// Step 3: Create load job
const loadJob = await client.cron.entries.create(userId, {
  command: '/scripts/load-data.sh',
  schedule: '0 2 * * *'  // 2:00 AM daily
})

// Verify all jobs were created
const allEntries = await client.cron.entries.listAll(userId)
console.log(`Pipeline created with ${allEntries.length} jobs`)
```

### Error Recovery: Retry Failed Job Creation

Handle transient failures when creating jobs.

```
async function createEntryWithRetry(
  client: HoodyClient,
  user: string,
  data: { command: string; schedule: string },
  maxRetries: number = 3
) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const entry = await client.cron.entries.create(user, data)
      return entry
    } catch (error) {
      console.error(`Attempt ${attempt} failed:`, error)
      if (attempt === maxRetries) throw error
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt))
    }
  }
}

// Usage
const entry = await createEntryWithRetry(client, 'my-user', {
  command: '/scripts/critical-task.sh',
  schedule: '*/15 * * * *'  // Every 15 minutes
})
```

### Batch Operations: Update Multiple Entries

Efficiently update a group of related entries.

```
async function updateScheduleForUser(
  client: HoodyClient,
  user: string,
  newSchedule: string
) {
  const entries = await client.cron.entries.listAll(user)
  
  const results = await Promise.allSettled(
    entries.map((entry: any) =>
      client.cron.entries.update(user, entry.id, { schedule: newSchedule })
    )
  )

  const succeeded = results.filter(r => r.status === 'fulfilled').length
  const failed = results.filter(r => r.status === 'rejected').length

  console.log(`Updated ${succeeded} entries, ${failed} failed`)
  return { succeeded, failed }
}
```

### Health Check Integration

Verify the cron service is operational before performing operations.

```
async function ensureServiceHealthy(client: HoodyClient): Promise<boolean> {
  try {
    const health = await client.cron.health.check()
    console.log('Service health:', health)
    return true
  } catch (error) {
    console.error('Service unhealthy:', error)
    return false
  }
}

// Usage in critical workflows
if (await ensureServiceHealthy(client)) {
  const entry = await client.cron.entries.create('my-user', {
    command: '/scripts/important-task.sh',
    schedule: '0 * * * *'  // Every hour
  })
} else {
  console.error('Cannot proceed: cron service is unhealthy')
}
```

### Cleanup: Remove All Entries for a User

Safely remove all cron entries when decommissioning a user.

```
async function cleanupUserEntries(client: HoodyClient, user: string) {
  const entries = await client.cron.entries.listAll(user)
  
  let deleted = 0
  for (const entry of entries) {
    try {
      await client.cron.entries.delete(user, entry.id)
      deleted++
    } catch (error) {
      console.error(`Failed to delete entry ${entry.id}:`, error)
    }
  }

  console.log(`Cleaned up ${deleted}/${entries.length} entries for user ${user}`)
}
```

---

## Quick Reference

### Essential Endpoints

| Operation | SDK Method | HTTP |
|-----------|------------|------|
| List all crontabs | `client.cron.crontab.listGlobal()` | GET /crontab |
| Get user crontab | `client.cron.crontab.get(user)` | GET /users/{user}/crontab |
| Update user crontab | `client.cron.crontab.put(user, data)` | PUT /users/{user}/crontab |
| List user entries | `client.cron.entries.list(user)` | GET /users/{user}/entries |
| Create entry | `client.cron.entries.create(user, data)` | POST /users/{user}/entries |
| Get entry | `client.cron.entries.get(user, id)` | GET /users/{user}/entries/{id} |
| Update entry | `client.cron.entries.update(user, id, data)` | PATCH /users/{user}/entries/{id} |
| Delete entry | `client.cron.entries.delete(user, id)` | DELETE /users/{user}/entries/{id} |
| Health check | `client.cron.health.check()` | GET /health |

### Required Parameters

**Create Entry:**
```
{
  command: string,   // Required: The command to execute
  schedule: string   // Required: Cron expression (e.g., "0 2 * * *")
}
```

**Update Crontab:**
```
{
  crontab: string    // Required: Raw crontab content
}
```

### Common Cron Expressions

| Expression | Description |
|------------|-------------|
| `* * * * *` | Every minute |
| `0 * * * *` | Every hour |
| `0 0 * * *` | Daily at midnight |
| `0 2 * * *` | Daily at 2:00 AM |
| `0 0 * * 0` | Weekly on Sunday |
| `0 0 1 * *` | Monthly on the 1st |
| `*/15 * * * *` | Every 15 minutes |

### SDK Client Setup

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({
  baseURL: 'https://api.hoody.icu',
  token: 'YOUR_TOKEN'
})
```

### Response Patterns

All list endpoints support pagination via `page` and `limit` parameters. Use `listAll()` or `listIterator()` variants for automatic pagination handling.