{"id":51197884,"url":"https://github.com/anandchowdhary/helios","last_synced_at":"2026-06-27T22:02:46.988Z","repository":{"id":362818002,"uuid":"1130696727","full_name":"AnandChowdhary/helios","owner":"AnandChowdhary","description":"🌐 Cloud Claude Code API Service: Run Claude Code instances on-demand through a simple REST API.","archived":false,"fork":false,"pushed_at":"2026-02-28T23:14:39.000Z","size":445,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-06T04:29:22.246Z","etag":null,"topics":["api","claude-code"],"latest_commit_sha":null,"homepage":"https://helios.getelysium.workers.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AnandChowdhary.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-08T21:57:58.000Z","updated_at":"2026-01-09T20:54:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/AnandChowdhary/helios","commit_stats":null,"previous_names":["anandchowdhary/helios"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/AnandChowdhary/helios","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnandChowdhary%2Fhelios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnandChowdhary%2Fhelios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnandChowdhary%2Fhelios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnandChowdhary%2Fhelios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AnandChowdhary","download_url":"https://codeload.github.com/AnandChowdhary/helios/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnandChowdhary%2Fhelios/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34869004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","claude-code"],"created_at":"2026-06-27T22:02:45.950Z","updated_at":"2026-06-27T22:02:46.979Z","avatar_url":"https://github.com/AnandChowdhary.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Helios\n\n**Cloud Claude Code API Service** — Run Claude Code instances on-demand through a simple REST API.\n\nHelios is a developer API service that provides on-demand Claude Code instances in the cloud. Developers can programmatically spin up isolated containers, clone repositories, execute Claude Code tasks, and retrieve results — all through a simple REST API.\n\nThink of it as **\"Claude Code as a Service\"** — the same powerful agentic coding assistant, but accessible via API for automation, CI/CD pipelines, and building AI-powered developer tools.\n\n## Use Cases\n\n- **Automated Code Review** — Trigger Claude Code to review PRs on push\n- **Bug Fixing Pipelines** — Submit issues and get back code fixes\n- **Code Generation** — Generate features from natural language specs\n- **Refactoring at Scale** — Batch process repositories for migrations\n- **Developer Tools** — Build IDE plugins, Slack bots, or CLI tools powered by Claude Code\n\n## Features\n\n- 🚀 **Simple API** — One endpoint to run a task, one to check status\n- 📡 **Streaming Support** — Real-time output via Server-Sent Events (SSE)\n- 🔐 **Credential Passthrough** — API keys passed per-request, never stored\n- 📦 **Isolated Execution** — Each task runs in its own ephemeral container\n- 🌐 **Edge Deployment** — Runs on Cloudflare Workers for global low-latency\n\n## Tech Stack\n\n| Component     | Technology                      |\n| ------------- | ------------------------------- |\n| Runtime       | Cloudflare Workers              |\n| Containers    | Cloudflare Containers           |\n| Database      | Cloudflare KV (task metadata)   |\n| Storage       | Cloudflare R2 (logs, artifacts) |\n| Rate Limiting | Cloudflare Rate Limiting API    |\n| Queue         | Cloudflare Queues               |\n| Framework     | Hono                            |\n| Validation    | Zod                             |\n| Language      | TypeScript                      |\n\n## Quick Start\n\n### Prerequisites\n\n- Node.js 22+\n- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/install-and-update/)\n- Cloudflare account\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/AnandChowdhary/helios.git\ncd helios\n\n# Install dependencies\nnpm install\n\n# Start local development server\nnpm run dev\n```\n\n### Configuration\n\nCopy `wrangler.toml.example` to `wrangler.toml` and update with your Cloudflare resource IDs:\n\n```toml\nname = \"helios\"\nmain = \"src/index.ts\"\ncompatibility_date = \"2025-01-01\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[[kv_namespaces]]\nbinding = \"TASKS\"\nid = \"\u003cyour-tasks-kv-id\u003e\"\n\n[[kv_namespaces]]\nbinding = \"API_KEYS\"\nid = \"\u003cyour-api-keys-kv-id\u003e\"\n\n[[r2_buckets]]\nbinding = \"ARTIFACTS\"\nbucket_name = \"helios-artifacts\"\n```\n\n## API Reference\n\n### Authentication\n\nAll endpoints under `/v1/*` require authentication via API key in the Authorization header:\n\n```\nAuthorization: Bearer \u003cHELIOS_API_KEY\u003e\n```\n\n### Base URL\n\n**Production:**\n\n```\nhttps://helios.getelysium.workers.dev\n```\n\n**Staging:**\n\n```\nhttps://helios-staging.getelysium.workers.dev\n```\n\n---\n\n### Create Task\n\nCreates a new Claude Code task to execute against a repository.\n\n```http\nPOST /v1/tasks\n```\n\n#### Request Fields\n\n| Field                          | Type     | Required | Default                                     | Description                                           |\n| ------------------------------ | -------- | -------- | ------------------------------------------- | ----------------------------------------------------- |\n| `prompt`                       | string   | Yes      | -                                           | The task prompt (1-100,000 characters)                |\n| `repository.url`               | string   | Yes      | -                                           | Git repository URL (GitHub, GitLab, or Bitbucket)     |\n| `repository.branch`            | string   | No       | `main`                                      | Branch to clone                                       |\n| `repository.credentials.type`  | string   | No       | -                                           | Authentication type (`token`)                         |\n| `repository.credentials.value` | string   | No       | -                                           | Authentication token (e.g., `ghp_xxx`)                |\n| `claude.apiKey`                | string   | Yes      | -                                           | Anthropic API key (must start with `sk-ant-`)         |\n| `claude.model`                 | string   | No       | `claude-sonnet-4-5`                         | Model to use (`claude-sonnet-4-5` or `claude-opus-4`) |\n| `claude.maxTurns`              | number   | No       | `10`                                        | Maximum conversation turns (1-50)                     |\n| `claude.systemPrompt`          | string   | No       | -                                           | Custom system prompt (max 10,000 characters)          |\n| `options.timeout`              | number   | No       | `300`                                       | Task timeout in seconds (30-600)                      |\n| `options.allowedTools`         | string[] | No       | `[\"Read\", \"Write\", \"Bash\", \"Glob\", \"Grep\"]` | Claude Code tools to allow                            |\n| `options.workingDirectory`     | string   | No       | `/workspace`                                | Working directory in container                        |\n| `options.environment`          | object   | No       | -                                           | Environment variables to set                          |\n| `output.mode`                  | string   | No       | `sync`                                      | Output mode (`sync` or `async`)                       |\n| `output.webhook.url`           | string   | No       | -                                           | Webhook URL for async notifications                   |\n| `output.webhook.secret`        | string   | No       | -                                           | Webhook HMAC secret (min 16 characters)               |\n\n#### Example: Async Task (curl)\n\n```bash\ncurl -X POST https://helios.getelysium.workers.dev/v1/tasks \\\n  -H \"Authorization: Bearer $HELIOS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"prompt\": \"Fix the failing tests in the auth module\",\n    \"repository\": {\n      \"url\": \"https://github.com/user/repo.git\",\n      \"branch\": \"main\",\n      \"credentials\": {\n        \"type\": \"token\",\n        \"value\": \"'\"$GITHUB_TOKEN\"'\"\n      }\n    },\n    \"claude\": {\n      \"apiKey\": \"'\"$ANTHROPIC_API_KEY\"'\",\n      \"model\": \"claude-sonnet-4-5\",\n      \"maxTurns\": 10\n    },\n    \"output\": {\n      \"mode\": \"async\"\n    }\n  }'\n```\n\n**Response (202 Accepted):**\n\n```json\n{\n  \"taskId\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"status\": \"pending\",\n  \"createdAt\": \"2025-01-08T10:00:00.000Z\",\n  \"statusUrl\": \"https://helios.getelysium.workers.dev/v1/tasks/550e8400-e29b-41d4-a716-446655440000\"\n}\n```\n\n#### Example: Sync Task with SSE Streaming (curl)\n\n```bash\ncurl -X POST https://helios.getelysium.workers.dev/v1/tasks \\\n  -H \"Authorization: Bearer $HELIOS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: text/event-stream\" \\\n  -d '{\n    \"prompt\": \"List all TypeScript files and count the lines of code\",\n    \"repository\": {\n      \"url\": \"https://github.com/user/repo.git\"\n    },\n    \"claude\": {\n      \"apiKey\": \"'\"$ANTHROPIC_API_KEY\"'\",\n      \"maxTurns\": 5\n    },\n    \"output\": {\n      \"mode\": \"sync\"\n    }\n  }'\n```\n\n**Response (200 OK, SSE Stream):**\n\n```\nevent: status\ndata: {\"status\":\"starting\",\"taskId\":\"550e8400-e29b-41d4-a716-446655440000\"}\n\nevent: status\ndata: {\"status\":\"running\",\"taskId\":\"550e8400-e29b-41d4-a716-446655440000\"}\n\nevent: message\ndata: {\"type\":\"assistant\",\"content\":\"I'll search for TypeScript files...\"}\n\nevent: tool_use\ndata: {\"tool\":\"Glob\",\"input\":{\"pattern\":\"**/*.ts\"}}\n\nevent: complete\ndata: {\"success\":true,\"summary\":\"Found 42 TypeScript files with 3,500 lines of code\"}\n```\n\n---\n\n### Get Task Status\n\nRetrieve the current status and result of a task.\n\n```http\nGET /v1/tasks/:taskId\n```\n\n#### Example (curl)\n\n```bash\ncurl https://helios.getelysium.workers.dev/v1/tasks/550e8400-e29b-41d4-a716-446655440000 \\\n  -H \"Authorization: Bearer $HELIOS_API_KEY\"\n```\n\n**Response (200 OK):**\n\n```json\n{\n  \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"status\": \"completed\",\n  \"prompt\": \"Fix the failing tests\",\n  \"repository\": {\n    \"url\": \"https://github.com/user/repo.git\",\n    \"branch\": \"main\"\n  },\n  \"createdAt\": \"2025-01-08T10:00:00.000Z\",\n  \"startedAt\": \"2025-01-08T10:00:05.000Z\",\n  \"completedAt\": \"2025-01-08T10:02:30.000Z\",\n  \"result\": {\n    \"success\": true,\n    \"summary\": \"Fixed 3 failing tests in auth module\",\n    \"filesChanged\": [\n      {\n        \"path\": \"src/auth/login.ts\",\n        \"additions\": 12,\n        \"deletions\": 5\n      }\n    ],\n    \"diff\": \"diff --git a/src/auth/login.ts...\"\n  }\n}\n```\n\n---\n\n### Cancel Task\n\nCancel a pending or running task.\n\n```http\nPOST /v1/tasks/:taskId/cancel\n```\n\n#### Example (curl)\n\n```bash\ncurl -X POST https://helios.getelysium.workers.dev/v1/tasks/550e8400-e29b-41d4-a716-446655440000/cancel \\\n  -H \"Authorization: Bearer $HELIOS_API_KEY\"\n```\n\n**Response (200 OK):**\n\n```json\n{\n  \"taskId\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"status\": \"cancelled\",\n  \"cancelledAt\": \"2025-01-08T10:01:00.000Z\"\n}\n```\n\n---\n\n### Get Task Logs\n\nRetrieve the full execution logs for a completed task.\n\n```http\nGET /v1/tasks/:taskId/logs\n```\n\n#### Example (curl)\n\n```bash\ncurl https://helios.getelysium.workers.dev/v1/tasks/550e8400-e29b-41d4-a716-446655440000/logs \\\n  -H \"Authorization: Bearer $HELIOS_API_KEY\"\n```\n\n**Response (200 OK, text/plain):**\n\n```\n[2025-01-08T10:00:05.000Z] Starting task...\n[2025-01-08T10:00:06.000Z] Cloning repository...\n[2025-01-08T10:00:10.000Z] Running Claude Code...\n...\n```\n\n---\n\n### Get Task Diff\n\nRetrieve the git diff of all changes made by the task.\n\n```http\nGET /v1/tasks/:taskId/diff\n```\n\n#### Example (curl)\n\n```bash\ncurl https://helios.getelysium.workers.dev/v1/tasks/550e8400-e29b-41d4-a716-446655440000/diff \\\n  -H \"Authorization: Bearer $HELIOS_API_KEY\"\n```\n\n**Response (200 OK, text/x-diff):**\n\n```diff\ndiff --git a/src/auth/login.ts b/src/auth/login.ts\nindex abc123..def456 100644\n--- a/src/auth/login.ts\n+++ b/src/auth/login.ts\n@@ -10,5 +10,7 @@ export function login(user: string, pass: string) {\n+  // Validate input before processing\n+  if (!user || !pass) throw new Error('Invalid credentials');\n   return authenticate(user, pass);\n }\n```\n\n---\n\n### Health Check\n\nCheck if the API is healthy (no authentication required).\n\n```http\nGET /health\n```\n\n#### Example (curl)\n\n```bash\ncurl https://helios.getelysium.workers.dev/health\n```\n\n**Response (200 OK):**\n\n```json\n{\n  \"status\": \"healthy\",\n  \"timestamp\": \"2025-01-08T10:00:00.000Z\"\n}\n```\n\n---\n\n## Task Status Values\n\n| Status      | Description                         |\n| ----------- | ----------------------------------- |\n| `pending`   | Task is queued and waiting to start |\n| `running`   | Task is currently executing         |\n| `completed` | Task finished successfully          |\n| `failed`    | Task finished with an error         |\n| `cancelled` | Task was cancelled by the user      |\n\n---\n\n## Error Responses\n\nAll error responses follow this format:\n\n```json\n{\n  \"error\": {\n    \"message\": \"Description of the error\"\n  }\n}\n```\n\n### HTTP Status Codes\n\n| Status | Description                                             |\n| ------ | ------------------------------------------------------- |\n| `200`  | Success                                                 |\n| `202`  | Accepted (async task created)                           |\n| `400`  | Bad Request - Invalid input or task cannot be cancelled |\n| `401`  | Unauthorized - Missing or invalid API key               |\n| `404`  | Not Found - Task or resource not found                  |\n| `429`  | Too Many Requests - Rate limit exceeded                 |\n| `500`  | Internal Server Error                                   |\n\n### Rate Limiting\n\nRate limits are applied per API key. When rate limited, the response includes these headers:\n\n```\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 0\nX-RateLimit-Reset: 1704708000000\n```\n\n---\n\n## SSE Event Types\n\nWhen using sync mode, the response is a Server-Sent Events stream with these event types:\n\n| Event         | Description                                 |\n| ------------- | ------------------------------------------- |\n| `status`      | Task status updates (`starting`, `running`) |\n| `message`     | Claude's text responses                     |\n| `tool_use`    | Tool invocation by Claude                   |\n| `tool_result` | Result from tool execution                  |\n| `complete`    | Task completed with final result            |\n| `error`       | Error occurred during execution             |\n\n---\n\n## Code Examples\n\n### TypeScript/JavaScript\n\n#### Create an Async Task\n\n```typescript\nconst response = await fetch(\"https://helios.getelysium.workers.dev/v1/tasks\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.HELIOS_API_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    prompt: \"Add unit tests for the auth module\",\n    repository: {\n      url: \"https://github.com/user/repo.git\",\n      branch: \"main\",\n      credentials: {\n        type: \"token\",\n        value: process.env.GITHUB_TOKEN,\n      },\n    },\n    claude: {\n      apiKey: process.env.ANTHROPIC_API_KEY,\n      model: \"claude-sonnet-4-5\",\n      maxTurns: 15,\n    },\n    output: {\n      mode: \"async\",\n    },\n  }),\n});\n\nconst { taskId, statusUrl } = await response.json();\nconsole.log(`Task created: ${taskId}`);\nconsole.log(`Check status at: ${statusUrl}`);\n```\n\n#### Poll for Task Completion\n\n```typescript\nasync function waitForTask(taskId: string): Promise\u003cany\u003e {\n  const maxAttempts = 60;\n  const pollInterval = 5000; // 5 seconds\n\n  for (let i = 0; i \u003c maxAttempts; i++) {\n    const response = await fetch(\n      `https://helios.getelysium.workers.dev/v1/tasks/${taskId}`,\n      {\n        headers: {\n          Authorization: `Bearer ${process.env.HELIOS_API_KEY}`,\n        },\n      },\n    );\n\n    const task = await response.json();\n\n    if (task.status === \"completed\" || task.status === \"failed\") {\n      return task;\n    }\n\n    await new Promise((resolve) =\u003e setTimeout(resolve, pollInterval));\n  }\n\n  throw new Error(\"Task timed out\");\n}\n\nconst result = await waitForTask(taskId);\nconsole.log(`Task ${result.status}:`, result.result?.summary);\n```\n\n#### Stream Sync Task with EventSource\n\n```typescript\n// Note: EventSource doesn't support custom headers in browsers.\n// Use fetch with ReadableStream for full control.\n\nasync function streamTask(taskPayload: object) {\n  const response = await fetch(\n    \"https://helios.getelysium.workers.dev/v1/tasks\",\n    {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${process.env.HELIOS_API_KEY}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        ...taskPayload,\n        output: { mode: \"sync\" },\n      }),\n    },\n  );\n\n  if (!response.body) {\n    throw new Error(\"No response body\");\n  }\n\n  const reader = response.body.getReader();\n  const decoder = new TextDecoder();\n  let buffer = \"\";\n\n  while (true) {\n    const { done, value } = await reader.read();\n    if (done) break;\n\n    buffer += decoder.decode(value, { stream: true });\n    const lines = buffer.split(\"\\n\");\n    buffer = lines.pop() || \"\";\n\n    let currentEvent = \"message\";\n    for (const line of lines) {\n      if (line.startsWith(\"event: \")) {\n        currentEvent = line.slice(7);\n      } else if (line.startsWith(\"data: \")) {\n        const data = JSON.parse(line.slice(6));\n        console.log(`[${currentEvent}]`, data);\n\n        if (currentEvent === \"complete\") {\n          return data;\n        }\n        if (currentEvent === \"error\") {\n          throw new Error(data.message);\n        }\n      }\n    }\n  }\n}\n```\n\n#### Simple Wrapper Class\n\n```typescript\nclass HeliosClient {\n  constructor(\n    private apiKey: string,\n    private baseUrl = \"https://helios.getelysium.workers.dev\",\n  ) {}\n\n  async createTask(options: {\n    prompt: string;\n    repoUrl: string;\n    branch?: string;\n    githubToken?: string;\n    anthropicApiKey: string;\n    async?: boolean;\n  }) {\n    const response = await fetch(`${this.baseUrl}/v1/tasks`, {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        prompt: options.prompt,\n        repository: {\n          url: options.repoUrl,\n          branch: options.branch ?? \"main\",\n          credentials: options.githubToken\n            ? { type: \"token\", value: options.githubToken }\n            : undefined,\n        },\n        claude: {\n          apiKey: options.anthropicApiKey,\n        },\n        output: {\n          mode: options.async ? \"async\" : \"sync\",\n        },\n      }),\n    });\n\n    if (!response.ok) {\n      const error = await response.json();\n      throw new Error(error.error?.message ?? \"Request failed\");\n    }\n\n    return response.json();\n  }\n\n  async getTask(taskId: string) {\n    const response = await fetch(`${this.baseUrl}/v1/tasks/${taskId}`, {\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n      },\n    });\n\n    if (!response.ok) {\n      const error = await response.json();\n      throw new Error(error.error?.message ?? \"Request failed\");\n    }\n\n    return response.json();\n  }\n\n  async cancelTask(taskId: string) {\n    const response = await fetch(`${this.baseUrl}/v1/tasks/${taskId}/cancel`, {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n      },\n    });\n\n    if (!response.ok) {\n      const error = await response.json();\n      throw new Error(error.error?.message ?? \"Request failed\");\n    }\n\n    return response.json();\n  }\n}\n\n// Usage\nconst helios = new HeliosClient(process.env.HELIOS_API_KEY!);\n\nconst { taskId } = await helios.createTask({\n  prompt: \"Refactor the utils module to use TypeScript\",\n  repoUrl: \"https://github.com/user/repo.git\",\n  anthropicApiKey: process.env.ANTHROPIC_API_KEY!,\n  async: true,\n});\n\n// Later...\nconst task = await helios.getTask(taskId);\n```\n\n### Python\n\n#### Create an Async Task\n\n```python\nimport os\nimport requests\n\nresponse = requests.post(\n    \"https://helios.getelysium.workers.dev/v1/tasks\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['HELIOS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json={\n        \"prompt\": \"Add unit tests for the auth module\",\n        \"repository\": {\n            \"url\": \"https://github.com/user/repo.git\",\n            \"branch\": \"main\",\n            \"credentials\": {\n                \"type\": \"token\",\n                \"value\": os.environ.get(\"GITHUB_TOKEN\"),\n            },\n        },\n        \"claude\": {\n            \"apiKey\": os.environ[\"ANTHROPIC_API_KEY\"],\n            \"model\": \"claude-sonnet-4-5\",\n            \"maxTurns\": 15,\n        },\n        \"output\": {\n            \"mode\": \"async\",\n        },\n    },\n)\n\ndata = response.json()\nprint(f\"Task created: {data['taskId']}\")\nprint(f\"Check status at: {data['statusUrl']}\")\n```\n\n#### Poll for Task Completion\n\n```python\nimport time\nimport requests\nimport os\n\ndef wait_for_task(task_id: str, max_attempts: int = 60, poll_interval: int = 5):\n    \"\"\"Wait for a task to complete, polling at regular intervals.\"\"\"\n    base_url = \"https://helios.getelysium.workers.dev\"\n    headers = {\"Authorization\": f\"Bearer {os.environ['HELIOS_API_KEY']}\"}\n\n    for _ in range(max_attempts):\n        response = requests.get(f\"{base_url}/v1/tasks/{task_id}\", headers=headers)\n        task = response.json()\n\n        if task[\"status\"] in (\"completed\", \"failed\"):\n            return task\n\n        time.sleep(poll_interval)\n\n    raise TimeoutError(\"Task timed out\")\n\n# Usage\nresult = wait_for_task(task_id)\nprint(f\"Task {result['status']}: {result.get('result', {}).get('summary', 'No summary')}\")\n```\n\n#### Stream Sync Task\n\n```python\nimport os\nimport json\nimport requests\n\ndef stream_task(payload: dict):\n    \"\"\"Stream a sync task and yield events.\"\"\"\n    response = requests.post(\n        \"https://helios.getelysium.workers.dev/v1/tasks\",\n        headers={\n            \"Authorization\": f\"Bearer {os.environ['HELIOS_API_KEY']}\",\n            \"Content-Type\": \"application/json\",\n        },\n        json={**payload, \"output\": {\"mode\": \"sync\"}},\n        stream=True,\n    )\n\n    current_event = \"message\"\n    for line in response.iter_lines():\n        if not line:\n            continue\n\n        line = line.decode(\"utf-8\")\n        if line.startswith(\"event: \"):\n            current_event = line[7:]\n        elif line.startswith(\"data: \"):\n            data = json.loads(line[6:])\n            yield current_event, data\n\n            if current_event == \"complete\":\n                return\n            if current_event == \"error\":\n                raise Exception(data.get(\"message\", \"Unknown error\"))\n\n# Usage\nfor event_type, data in stream_task({\n    \"prompt\": \"List all Python files in the repository\",\n    \"repository\": {\"url\": \"https://github.com/user/repo.git\"},\n    \"claude\": {\"apiKey\": os.environ[\"ANTHROPIC_API_KEY\"]},\n}):\n    print(f\"[{event_type}]\", data)\n```\n\n#### Simple Client Class\n\n```python\nimport os\nimport requests\nfrom typing import Optional\n\nclass HeliosClient:\n    def __init__(self, api_key: str, base_url: str = \"https://helios.getelysium.workers.dev\"):\n        self.api_key = api_key\n        self.base_url = base_url\n\n    def _headers(self) -\u003e dict:\n        return {\"Authorization\": f\"Bearer {self.api_key}\"}\n\n    def create_task(\n        self,\n        prompt: str,\n        repo_url: str,\n        anthropic_api_key: str,\n        branch: str = \"main\",\n        github_token: Optional[str] = None,\n        async_mode: bool = False,\n    ) -\u003e dict:\n        \"\"\"Create a new task.\"\"\"\n        payload = {\n            \"prompt\": prompt,\n            \"repository\": {\n                \"url\": repo_url,\n                \"branch\": branch,\n            },\n            \"claude\": {\"apiKey\": anthropic_api_key},\n            \"output\": {\"mode\": \"async\" if async_mode else \"sync\"},\n        }\n\n        if github_token:\n            payload[\"repository\"][\"credentials\"] = {\"type\": \"token\", \"value\": github_token}\n\n        response = requests.post(\n            f\"{self.base_url}/v1/tasks\",\n            headers={**self._headers(), \"Content-Type\": \"application/json\"},\n            json=payload,\n        )\n        response.raise_for_status()\n        return response.json()\n\n    def get_task(self, task_id: str) -\u003e dict:\n        \"\"\"Get task status and result.\"\"\"\n        response = requests.get(f\"{self.base_url}/v1/tasks/{task_id}\", headers=self._headers())\n        response.raise_for_status()\n        return response.json()\n\n    def cancel_task(self, task_id: str) -\u003e dict:\n        \"\"\"Cancel a running task.\"\"\"\n        response = requests.post(f\"{self.base_url}/v1/tasks/{task_id}/cancel\", headers=self._headers())\n        response.raise_for_status()\n        return response.json()\n\n    def get_diff(self, task_id: str) -\u003e str:\n        \"\"\"Get the git diff from a completed task.\"\"\"\n        response = requests.get(f\"{self.base_url}/v1/tasks/{task_id}/diff\", headers=self._headers())\n        response.raise_for_status()\n        return response.text\n\n# Usage\nhelios = HeliosClient(os.environ[\"HELIOS_API_KEY\"])\n\nresult = helios.create_task(\n    prompt=\"Refactor the utils module to use TypeScript\",\n    repo_url=\"https://github.com/user/repo.git\",\n    anthropic_api_key=os.environ[\"ANTHROPIC_API_KEY\"],\n    async_mode=True,\n)\n\nprint(f\"Task ID: {result['taskId']}\")\n```\n\n---\n\n## Practical Use Cases\n\n### GitHub Actions: Auto-fix Failing Tests\n\nAdd this workflow to automatically create a PR when tests fail:\n\n```yaml\n# .github/workflows/auto-fix-tests.yml\nname: Auto-fix Failing Tests\n\non:\n  workflow_run:\n    workflows: [\"CI\"]\n    types: [completed]\n\njobs:\n  auto-fix:\n    runs-on: ubuntu-latest\n    if: ${{ github.event.workflow_run.conclusion == 'failure' }}\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Create fix task\n        id: helios\n        run: |\n          RESPONSE=$(curl -s -X POST https://helios.getelysium.workers.dev/v1/tasks \\\n            -H \"Authorization: Bearer ${{ secrets.HELIOS_API_KEY }}\" \\\n            -H \"Content-Type: application/json\" \\\n            -d '{\n              \"prompt\": \"The CI tests are failing. Please analyze the test output, identify the issues, and fix them. Run the tests after fixing to verify.\",\n              \"repository\": {\n                \"url\": \"https://github.com/${{ github.repository }}.git\",\n                \"branch\": \"${{ github.event.workflow_run.head_branch }}\",\n                \"credentials\": {\n                  \"type\": \"token\",\n                  \"value\": \"${{ secrets.GITHUB_TOKEN }}\"\n                }\n              },\n              \"claude\": {\n                \"apiKey\": \"${{ secrets.ANTHROPIC_API_KEY }}\",\n                \"maxTurns\": 20\n              },\n              \"output\": {\n                \"mode\": \"async\"\n              }\n            }')\n          echo \"task_id=$(echo $RESPONSE | jq -r '.taskId')\" \u003e\u003e $GITHUB_OUTPUT\n\n      - name: Wait for task\n        run: |\n          TASK_ID=\"${{ steps.helios.outputs.task_id }}\"\n          for i in {1..60}; do\n            STATUS=$(curl -s https://helios.getelysium.workers.dev/v1/tasks/$TASK_ID \\\n              -H \"Authorization: Bearer ${{ secrets.HELIOS_API_KEY }}\" | jq -r '.status')\n            echo \"Task status: $STATUS\"\n            if [ \"$STATUS\" = \"completed\" ] || [ \"$STATUS\" = \"failed\" ]; then\n              break\n            fi\n            sleep 10\n          done\n```\n\n### Slack Bot: Code Review on Command\n\n```typescript\n// Slack bot handler for /review command\nimport { App } from \"@slack/bolt\";\n\nconst app = new App({\n  token: process.env.SLACK_BOT_TOKEN,\n  signingSecret: process.env.SLACK_SIGNING_SECRET,\n});\n\napp.command(\"/review\", async ({ command, ack, respond }) =\u003e {\n  await ack();\n\n  // Parse: /review https://github.com/user/repo/pull/123\n  const prUrl = command.text.trim();\n  const match = prUrl.match(/github\\.com\\/(.+)\\/(.+)\\/pull\\/(\\d+)/);\n\n  if (!match) {\n    await respond(\"Please provide a valid GitHub PR URL\");\n    return;\n  }\n\n  const [, owner, repo, prNumber] = match;\n\n  await respond(`Starting code review for PR #${prNumber}...`);\n\n  // Create Helios task\n  const response = await fetch(\n    \"https://helios.getelysium.workers.dev/v1/tasks\",\n    {\n      method: \"POST\",\n      headers: {\n        Authorization: `Bearer ${process.env.HELIOS_API_KEY}`,\n        \"Content-Type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        prompt: `Review the code changes in this pull request. Check for:\n        - Potential bugs or logic errors\n        - Security vulnerabilities\n        - Performance issues\n        - Code style and best practices\n        - Missing tests\n\n        Provide a detailed review with specific line references.`,\n        repository: {\n          url: `https://github.com/${owner}/${repo}.git`,\n          branch: `refs/pull/${prNumber}/head`,\n          credentials: {\n            type: \"token\",\n            value: process.env.GITHUB_TOKEN,\n          },\n        },\n        claude: {\n          apiKey: process.env.ANTHROPIC_API_KEY,\n          model: \"claude-sonnet-4-5\",\n          maxTurns: 10,\n        },\n        output: { mode: \"async\" },\n      }),\n    },\n  );\n\n  const { taskId } = await response.json();\n\n  // Poll and post result (simplified)\n  const result = await waitForTask(taskId);\n  await respond({\n    blocks: [\n      {\n        type: \"section\",\n        text: {\n          type: \"mrkdwn\",\n          text: `*Code Review Complete*\\n\\n${result.result?.summary || \"Review completed\"}`,\n        },\n      },\n    ],\n  });\n});\n```\n\n### Webhook Handler: Process Task Results\n\n```typescript\n// Express webhook handler\nimport express from \"express\";\nimport crypto from \"crypto\";\n\nconst app = express();\napp.use(express.raw({ type: \"application/json\" }));\n\napp.post(\"/webhooks/helios\", (req, res) =\u003e {\n  // Verify webhook signature\n  const signature = req.headers[\"x-helios-signature\"] as string;\n  const expectedSignature =\n    \"sha256=\" +\n    crypto\n      .createHmac(\"sha256\", process.env.WEBHOOK_SECRET!)\n      .update(req.body)\n      .digest(\"hex\");\n\n  if (signature !== expectedSignature) {\n    return res.status(401).send(\"Invalid signature\");\n  }\n\n  const event = JSON.parse(req.body.toString());\n\n  switch (event.event) {\n    case \"task.completed\":\n      console.log(`Task ${event.taskId} completed!`);\n      console.log(`Summary: ${event.result.summary}`);\n      console.log(`Files changed: ${event.result.filesChanged.length}`);\n      // Create PR, notify team, etc.\n      break;\n\n    case \"task.failed\":\n      console.error(`Task ${event.taskId} failed: ${event.error}`);\n      // Alert on-call, retry, etc.\n      break;\n  }\n\n  res.sendStatus(200);\n});\n\napp.listen(3000);\n```\n\n### CLI Tool: Quick Code Tasks\n\n```bash\n#!/bin/bash\n# helios-cli.sh - Simple CLI for Helios\n\nHELIOS_URL=\"https://helios.getelysium.workers.dev\"\n\nhelios_task() {\n    local prompt=\"$1\"\n    local repo=\"${2:-$(git remote get-url origin)}\"\n    local branch=\"${3:-$(git branch --show-current)}\"\n\n    echo \"Creating task...\"\n\n    RESPONSE=$(curl -s -X POST \"$HELIOS_URL/v1/tasks\" \\\n        -H \"Authorization: Bearer $HELIOS_API_KEY\" \\\n        -H \"Content-Type: application/json\" \\\n        -d \"{\n            \\\"prompt\\\": \\\"$prompt\\\",\n            \\\"repository\\\": {\n                \\\"url\\\": \\\"$repo\\\",\n                \\\"branch\\\": \\\"$branch\\\"\n            },\n            \\\"claude\\\": {\n                \\\"apiKey\\\": \\\"$ANTHROPIC_API_KEY\\\"\n            },\n            \\\"output\\\": {\\\"mode\\\": \\\"async\\\"}\n        }\")\n\n    TASK_ID=$(echo \"$RESPONSE\" | jq -r '.taskId')\n    echo \"Task ID: $TASK_ID\"\n\n    # Poll for completion\n    while true; do\n        STATUS=$(curl -s \"$HELIOS_URL/v1/tasks/$TASK_ID\" \\\n            -H \"Authorization: Bearer $HELIOS_API_KEY\" | jq -r '.status')\n\n        echo \"Status: $STATUS\"\n\n        if [ \"$STATUS\" = \"completed\" ] || [ \"$STATUS\" = \"failed\" ]; then\n            # Get full result\n            curl -s \"$HELIOS_URL/v1/tasks/$TASK_ID\" \\\n                -H \"Authorization: Bearer $HELIOS_API_KEY\" | jq '.result'\n            break\n        fi\n\n        sleep 5\n    done\n}\n\n# Usage: ./helios-cli.sh \"Add error handling to the API routes\"\nhelios_task \"$1\" \"$2\" \"$3\"\n```\n\n---\n\n## Development\n\n```bash\n# Start local development server\nnpm run dev\n\n# Run tests\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Run tests with coverage\nnpm run test:coverage\n\n# Lint code\nnpm run lint\n\n# Type check\nnpm run typecheck\n```\n\n## Deployment\n\n```bash\n# Deploy to staging\nnpm run deploy:staging\n\n# Deploy to production\nnpm run deploy:prod\n```\n\n### Setting Secrets\n\n```bash\nwrangler secret put WEBHOOK_SIGNING_KEY\n```\n\n## Project Structure\n\n```\nhelios/\n├── src/\n│   ├── index.ts              # Worker entry point\n│   ├── routes/\n│   │   └── tasks.ts          # Task API routes\n│   ├── middleware/\n│   │   ├── auth.ts           # API key authentication\n│   │   ├── rateLimit.ts      # Rate limiting\n│   │   └── validate.ts       # Request validation\n│   ├── schemas/\n│   │   └── task.ts           # Zod schemas\n│   ├── types/\n│   │   └── index.ts          # TypeScript types\n│   └── utils/\n│       └── errors.ts         # Error handling\n├── test/\n│   ├── unit/                 # Unit tests\n│   └── integration/          # Integration tests\n├── wrangler.toml             # Cloudflare configuration\n├── vitest.config.ts          # Test configuration\n└── package.json\n```\n\n## Security\n\n- **Credentials are never stored** — API keys passed per-request, used once, discarded\n- **Ephemeral containers** — Each task gets a fresh container, destroyed after completion\n- **Network isolation** — Containers can only access allowed endpoints\n- **Input validation** — All requests validated with Zod schemas\n- **Rate limiting** — Per-API-key rate limits prevent abuse\n\n## License\n\nMIT © [Anand Chowdhary](https://anandchowdhary.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanandchowdhary%2Fhelios","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanandchowdhary%2Fhelios","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanandchowdhary%2Fhelios/lists"}