{"id":42381112,"url":"https://github.com/tomblancdev/stromboli","last_synced_at":"2026-05-01T12:01:51.818Z","repository":{"id":334764965,"uuid":"1140059285","full_name":"tomblancdev/stromboli","owner":"tomblancdev","description":"Container orchestration API for spawning and managing isolated Claude Code agents in Podman containers","archived":false,"fork":false,"pushed_at":"2026-04-29T17:36:09.000Z","size":3306,"stargazers_count":1,"open_issues_count":14,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-29T19:08:26.833Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tomblancdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security/overview.md","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-22T19:18:28.000Z","updated_at":"2026-04-29T17:36:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tomblancdev/stromboli","commit_stats":null,"previous_names":["tomblancdev/stromboli"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/tomblancdev/stromboli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomblancdev%2Fstromboli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomblancdev%2Fstromboli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomblancdev%2Fstromboli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomblancdev%2Fstromboli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomblancdev","download_url":"https://codeload.github.com/tomblancdev/stromboli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomblancdev%2Fstromboli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32495949,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"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":[],"created_at":"2026-01-27T21:34:24.102Z","updated_at":"2026-05-01T12:01:51.801Z","avatar_url":"https://github.com/tomblancdev.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stromboli 🌋\n\n\u003e Container orchestration API for spawning and managing isolated Claude Code agents in Podman containers\n\nStromboli is a REST API that provides secure, isolated execution of Claude AI in containerized environments. It's designed for automating development workflows, CI/CD pipelines, code analysis, and AI-assisted development tasks.\n\n## Features\n\n- **Isolated Execution**: Each Claude instance runs in its own Podman container with resource limits\n- **Full Claude CLI Support**: All 40+ Claude headless mode options exposed via REST API\n- **Multiple Execution Modes**:\n  - Synchronous execution with immediate response\n  - Asynchronous execution with job tracking\n  - Server-Sent Events (SSE) for real-time streaming output\n- **Session Management**: Persistent conversation sessions across multiple API calls\n- **Webhook Notifications**: Get notified when async jobs complete\n- **Resource Controls**: CPU, memory, and timeout limits per container\n- **Security**: Token-based authentication, JWT with refresh tokens, workspace allowlisting, secret management\n- **Observability**: Prometheus metrics, OpenTelemetry distributed tracing, structured logging, request tracking\n- **Lifecycle Hooks**: Run commands at container creation and startup (install deps, start background services)\n- **Compose Environments**: Run Claude in multi-service environments with databases, caches, and other services\n- **Image Discovery**: List, inspect, search, and pull container images via API\n\n## Quick Start\n\n### Prerequisites\n\n- [Podman](https://podman.io/) v5+ installed and configured\n- Claude credentials (logged in via `claude` CLI)\n\n### Container Deployment (Recommended) 🐳\n\n```bash\n# 1. Enable Podman socket\nsystemctl --user enable --now podman.socket\n\n# 2. Setup Claude token (extracts from ~/.claude/.credentials.json)\nmake claude-setup\n\n# 3. Build images and start\nmake build-images\nmake container-start\n\n# 4. Test it works\ncurl http://localhost:8080/health\n```\n\n**That's it!** Stromboli is now running at `http://localhost:8080`.\n\n### Host Deployment (Alternative)\n\nFor development or when you prefer running directly on the host:\n\n```bash\n# 1. Configure Claude token\nmake claude-setup\n\n# 2. Build the agent image\nmake build-agent-image\n\n# 3. Build and run\nmake build\n./bin/stromboli\n\n# 4. Test it works\ncurl http://localhost:8080/health\n```\n\n### Test the API\n\n```bash\n# Health check\ncurl http://localhost:8080/health\n\n# Run Claude synchronously\ncurl -X POST http://localhost:8080/run \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"prompt\": \"What is the capital of France?\",\n    \"claude\": {\n      \"dangerously_skip_permissions\": true\n    }\n  }'\n```\n\n## API Endpoints\n\n### Execution\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/run` | POST | Execute Claude synchronously (returns output immediately) |\n| `/run/async` | POST | Execute Claude asynchronously (returns job ID) |\n| `/run/stream` | GET | Stream Claude output in real-time via SSE |\n\n### Job Management\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/jobs` | GET | List all async jobs |\n| `/jobs/{id}` | GET | Get job status and result |\n| `/jobs/{id}` | DELETE | Cancel a pending/running job |\n\n### Session Management\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/sessions` | GET | List all sessions |\n| `/sessions/{id}` | DELETE | Destroy session and all its data |\n\n### Authentication\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/auth/token` | POST | Generate JWT access and refresh tokens |\n| `/auth/refresh` | POST | Refresh an expiring access token |\n| `/auth/validate` | GET | Validate a token and return claims |\n| `/auth/logout` | POST | Invalidate a token (logout) |\n\n### System\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `/health` | GET | Health check with component status |\n| `/metrics` | GET | Prometheus metrics |\n| `/claude/status` | GET | Check Claude configuration |\n\n## Usage Examples\n\n### Synchronous Execution\n\nExecute Claude and get immediate response:\n\n```bash\ncurl -X POST http://localhost:8080/run \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"prompt\": \"Analyze this Go code for bugs\",\n    \"workdir\": \"/home/user/myproject\",\n    \"claude\": {\n      \"model\": \"sonnet\",\n      \"dangerously_skip_permissions\": true\n    },\n    \"podman\": {\n      \"timeout\": \"5m\",\n      \"memory\": \"1g\",\n      \"cpus\": \"2\"\n    }\n  }'\n```\n\n### Asynchronous Execution with Webhook\n\nStart a long-running task and get notified when complete:\n\n```bash\n# Start async job\ncurl -X POST http://localhost:8080/run/async \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"prompt\": \"Refactor this entire codebase for better maintainability\",\n    \"workdir\": \"/home/user/large-project\",\n    \"webhook_url\": \"https://myapp.com/webhook\",\n    \"claude\": {\n      \"model\": \"opus\",\n      \"dangerously_skip_permissions\": true\n    }\n  }'\n\n# Response: {\"job_id\": \"job-abc123def456\", \"session_id\": \"550e8400-...\"}\n\n# Poll for status\ncurl http://localhost:8080/jobs/job-abc123def456\n\n# Cancel if needed\ncurl -X DELETE http://localhost:8080/jobs/job-abc123def456\n```\n\n### Streaming Output\n\nGet real-time output via Server-Sent Events:\n\n```bash\ncurl -N http://localhost:8080/run/stream?prompt=Write%20a%20REST%20API%20in%20Go\n```\n\n### Session Continuation\n\nContinue a conversation across multiple API calls:\n\n```bash\n# First call (creates session)\ncurl -X POST http://localhost:8080/run \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"prompt\": \"Create a new Go project structure\",\n    \"workdir\": \"/home/user/newproject\"\n  }'\n\n# Response includes: \"session_id\": \"sess-abc123\"\n\n# Continue the conversation\ncurl -X POST http://localhost:8080/run \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"prompt\": \"Now add unit tests for the main package\",\n    \"workdir\": \"/home/user/newproject\",\n    \"claude\": {\n      \"session_id\": \"sess-abc123\",\n      \"resume\": true\n    }\n  }'\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `STROMBOLI_AUTH_ENABLED` | `true` | Enable token-based authentication. Server fails fast on startup if a JWT secret is missing/empty/placeholder. |\n| `STROMBOLI_API_TOKENS` | - | Comma-separated list of valid API tokens |\n| `STROMBOLI_JWT_SECRET` | - | Secret key for JWT signing (required when auth is enabled — must be ≥32 chars, no placeholders) |\n| `STROMBOLI_JWT_EXPIRY` | `24h` | JWT access token lifetime |\n| `STROMBOLI_RATE_LIMIT_ENABLED` | `false` | Enable rate limiting |\n| `STROMBOLI_RATE_LIMIT_RPS` | `10` | Requests per second limit |\n| `STROMBOLI_RATE_LIMIT_BURST` | `20` | Maximum burst size |\n| `STROMBOLI_TRACING_ENABLED` | `false` | Enable OpenTelemetry tracing |\n| `STROMBOLI_TRACING_ENDPOINT` | `localhost:4317` | OTLP collector endpoint |\n| `STROMBOLI_TRACING_INSECURE` | `false` | Disable TLS for the OTLP exporter (insecure — dev only) |\n| `STROMBOLI_METRICS_ENABLED` | `true` | Expose Prometheus metrics on a separate listener |\n| `STROMBOLI_METRICS_ADDRESS` | `127.0.0.1:9090` | Metrics listener bind address (localhost-only by default; never share-listen on `0.0.0.0`) |\n| `STROMBOLI_LOG_FORMAT` | `json` | Log encoder (`json` or `text`) |\n| `STROMBOLI_LOG_LEVEL` | `info` | Log level (`debug`, `info`, `warn`, `error`) |\n\n### Authentication\n\nAuth is **enabled by default**. Stromboli refuses to start if `STROMBOLI_JWT_SECRET` is missing/empty or a known placeholder — set a real secret (`openssl rand -base64 32`) before launching. Set `STROMBOLI_AUTH_ENABLED=false` only for local dev.\n\nInclude a Bearer token on every request:\n\n```bash\ncurl -X POST http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-token-here\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"Hello\"}'\n```\n\n#### JWT Authentication (Recommended)\n\nFor production, use JWT tokens with automatic expiration and refresh:\n\n```bash\n# Set JWT secret to enable JWT auth\nexport STROMBOLI_JWT_SECRET=\"your-256-bit-secret\"\n\n# Generate JWT tokens using API token\ncurl -X POST http://localhost:8080/auth/token \\\n  -H \"Authorization: Bearer your-api-token\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"client_id\": \"my-app\"}'\n\n# Response: {\"access_token\": \"eyJ...\", \"refresh_token\": \"eyJ...\", \"expires_in\": 86400}\n\n# Use JWT for requests\ncurl -H \"Authorization: Bearer eyJ...\" http://localhost:8080/run ...\n\n# Logout (invalidate token)\ncurl -X POST http://localhost:8080/auth/logout \\\n  -H \"Authorization: Bearer eyJ...\"\n```\n\nSee [docs/AUTHENTICATION.md](docs/AUTHENTICATION.md) for complete JWT setup.\n\n### Rate Limiting\n\nProtect your API from abuse by enabling rate limiting:\n\n```bash\nexport STROMBOLI_RATE_LIMIT_ENABLED=true\nexport STROMBOLI_RATE_LIMIT_RPS=10     # 10 requests per second\nexport STROMBOLI_RATE_LIMIT_BURST=20   # Allow burst of 20\n\n./bin/stromboli\n```\n\nRate limits are applied per IP address. When exceeded, the API returns `429 Too Many Requests`. See [docs/RATE_LIMITING.md](docs/RATE_LIMITING.md) for details.\n\n### Distributed Tracing\n\nEnable OpenTelemetry tracing for observability:\n\n```bash\nexport STROMBOLI_TRACING_ENABLED=true\nexport STROMBOLI_TRACING_ENDPOINT=\"jaeger:4317\"\nexport STROMBOLI_TRACING_SERVICE_NAME=\"stromboli-prod\"\n\n./bin/stromboli\n```\n\nTraces include HTTP requests, runner execution, and internal spans. Compatible with Jaeger, Grafana Tempo, and any OTLP-compatible backend. See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for details.\n\n### Resource Limits\n\nControl container resources via `podman` options:\n\n```json\n{\n  \"prompt\": \"...\",\n  \"podman\": {\n    \"timeout\": \"10m\",      // Container timeout (e.g., \"5m\", \"1h\")\n    \"memory\": \"2g\",        // Memory limit (e.g., \"512m\", \"1g\")\n    \"cpus\": \"2\",           // CPU limit (e.g., \"0.5\", \"2\")\n    \"cpu_shares\": 512,     // CPU shares (relative weight, default 1024)\n    \"volumes\": [           // Additional volume mounts\n      \"/data:/data:ro\"\n    ]\n  }\n}\n```\n\n### Claude Options\n\nStromboli exposes all Claude CLI options. See [docs/API.md](docs/API.md) for complete reference. Common options:\n\n```json\n{\n  \"claude\": {\n    \"model\": \"sonnet\",                         // sonnet, opus, haiku\n    \"session_id\": \"my-session-id\",             // Session ID for persistence\n    \"resume\": true,                            // Resume existing session\n    \"continue\": true,                          // Continue latest conversation\n    \"dangerously_skip_permissions\": true,      // Skip permission prompts (sandboxed only)\n    \"permission_mode\": \"bypassPermissions\",    // Permission mode\n    \"system_prompt\": \"You are a senior dev\",   // Custom system prompt\n    \"max_budget_usd\": 10.0,                    // Budget limit\n    \"max_turns\": 30,                           // Max agentic turns (0 = unlimited)\n    \"timeout\": \"30m\"                           // Claude timeout\n  }\n}\n```\n\n## Architecture\n\n```\n┌─────────────┐\n│   Client    │\n└──────┬──────┘\n       │ HTTP/REST\n       ▼\n┌─────────────────────────────────┐\n│      Stromboli API Server       │\n│  ┌────────────────────────────┐ │\n│  │  Gin HTTP Handlers         │ │\n│  └───────────┬────────────────┘ │\n│              ▼                   │\n│  ┌────────────────────────────┐ │\n│  │  Runner (Orchestration)    │ │\n│  └───────────┬────────────────┘ │\n│              ▼                   │\n│  ┌────────────────────────────┐ │\n│  │  Podman Command Builder    │ │\n│  └───────────┬────────────────┘ │\n└──────────────┼──────────────────┘\n               │ podman run\n               ▼\n       ┌──────────────────┐\n       │ Podman Container │\n       │  (isolated env)  │\n       │                  │\n       │  ┌────────────┐  │\n       │  │ Claude CLI │  │\n       │  └────────────┘  │\n       │                  │\n       │  /workspace      │\n       │  (mounted)       │\n       └──────────────────┘\n```\n\nKey components:\n\n- **API Layer**: HTTP handlers, authentication, request validation\n- **Runner Layer**: Orchestration logic, execution modes (sync/async/stream)\n- **Command Builders**: Construct Podman and Claude CLI commands\n- **Job Manager**: Track async jobs, cleanup, crash detection, webhook notifications\n- **Session Manager**: Persistent session state across calls\n- **Secrets Manager**: Secure Claude token handling via Podman secrets\n\nFor detailed architecture, see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).\n\n## Development\n\n### Project Structure\n\n```\nstromboli/\n├── cmd/stromboli/       # Application entry point\n├── internal/            # Private application code\n│   ├── api/            # HTTP handlers, middleware, routes\n│   ├── runner/         # Orchestration logic\n│   ├── podman/         # Podman command construction\n│   ├── claude/         # Claude command construction\n│   ├── job/            # Async job management\n│   ├── session/        # Session lifecycle\n│   ├── auth/           # Authentication\n│   └── types/          # Shared types\n├── docs/               # Documentation\n├── deployments/        # Docker/Podman files\n└── tests/              # Integration and E2E tests\n```\n\n### Building\n\n```bash\n# Build binary\nmake build\n\n# Run tests\nmake test\n\n# Run tests with coverage\nmake test-coverage\n\n# Run linter\nmake lint\n\n# Development with hot reload (requires air)\nmake dev\n```\n\n### Documentation Generation\n\n```bash\n# Generate all documentation\nmake docs\n\n# Generate Swagger/OpenAPI spec\nmake docs-swagger\n\n# Generate Go code documentation\nmake docs-godoc\n\n# Serve Swagger UI locally\nmake docs-serve\n```\n\n### Testing\n\n```bash\n# Run all tests\nmake test\n\n# Run with coverage report\nmake test-coverage\nopen coverage.html\n```\n\n## Production Deployment\n\n### Container Deployment (Recommended)\n\nThe easiest way to deploy Stromboli in production:\n\n```bash\n# 1. Enable Podman socket\nsystemctl --user enable --now podman.socket\n\n# 2. Setup Claude token\nmake claude-setup\n\n# 3. Build and start\nmake build-images\nmake container-start\n\n# 4. Verify\ncurl http://localhost:8080/health\n```\n\nThis uses `deployments/docker/compose.yml` which handles:\n- **Podman socket mount** - Stromboli talks to host Podman via socket\n- **Compose-managed secrets** - Claude token mounted automatically\n- **User namespace mapping** - `userns_mode: keep-id` for proper permissions\n- **Sessions persistence** - Stored in `/tmp/stromboli-sessions`\n\n**Container commands:**\n```bash\nmake container-start    # Start Stromboli\nmake container-stop     # Stop Stromboli\nmake container-restart  # Restart\nmake container-logs     # View logs\nmake container-status   # Check status\n```\n\n### Custom Compose Configuration\n\nOverride defaults with environment variables:\n\n```bash\n# Custom resources\nexport STROMBOLI_RESOURCES_MEMORY=\"2g\"\nexport STROMBOLI_RESOURCES_CPUS=\"4\"\nexport STROMBOLI_RESOURCES_TIMEOUT=\"1h\"\n\n# Enable authentication\nexport STROMBOLI_AUTH_ENABLED=\"true\"\nexport STROMBOLI_JWT_SECRET=\"$(openssl rand -base64 32)\"\n\n# Enable tracing\nexport STROMBOLI_TRACING_ENABLED=\"true\"\nexport STROMBOLI_TRACING_ENDPOINT=\"jaeger:4317\"\n\n# Start with custom config\nmake container-start\n```\n\n### Podman Compose File Reference\n\n```yaml\n# deployments/docker/compose.yml\nsecrets:\n  claude-token:\n    file: ${CLAUDE_SECRETS_FILE:-../../.claude-secrets}\n\nservices:\n  stromboli:\n    image: stromboli:latest\n    userns_mode: keep-id  # Critical for socket access\n    ports:\n      - \"8080:8080\"\n    secrets:\n      - claude-token\n    volumes:\n      - ${XDG_RUNTIME_DIR}/podman/podman.sock:/run/podman/podman.sock:ro\n      - /tmp/stromboli-sessions:/tmp/stromboli-sessions\n    environment:\n      STROMBOLI_AGENT_SECRETS_FILE: \"/run/secrets/claude-token\"\n      STROMBOLI_AGENT_SESSIONS_DIR: \"/tmp/stromboli-sessions\"\n      CONTAINER_HOST: \"unix:///run/podman/podman.sock\"\n```\n\n### Security Considerations\n\n1. **Enable Authentication**: Always set `STROMBOLI_AUTH_ENABLED=true` in production\n2. **Workspace Allowlist**: Configure allowed workspace paths in `main.go`\n3. **Resource Limits**: Set appropriate CPU/memory limits for containers\n4. **Network Isolation**: Run Stromboli in isolated network\n5. **Token Rotation**: Regularly rotate API tokens and Claude credentials\n6. **Audit Logging**: Enable structured logging and monitor API usage\n\n### Systemd Service\n\n```ini\n[Unit]\nDescription=Stromboli API Server\nAfter=network.target podman.service\n\n[Service]\nType=simple\nUser=stromboli\nWorkingDirectory=/opt/stromboli\nExecStart=/opt/stromboli/bin/stromboli\nEnvironment=\"STROMBOLI_AUTH_ENABLED=true\"\nEnvironment=\"STROMBOLI_API_TOKENS=token1,token2\"\nRestart=always\nRestartSec=10\n\n[Install]\nWantedBy=multi-user.target\n```\n\n## Documentation\n\n- **[User Guide](docs/USER_GUIDE.md)** - Start here! Complete guide for users\n- [API Reference](docs/API.md) - Complete API documentation with schemas\n- [Examples](docs/EXAMPLES.md) - Practical usage examples\n- [Architecture](docs/ARCHITECTURE.md) - System design and components\n- [Configuration](docs/CONFIGURATION.md) - All configuration options\n- [Authentication](docs/AUTHENTICATION.md) - JWT and token authentication\n- [Testing](docs/TESTING.md) - Testing guide (unit, integration, E2E)\n- [Vision](docs/VISION.md) - Project vision and roadmap\n\n## Contributing\n\nContributions are welcome! This project follows Test-Driven Development (TDD):\n\n1. Write failing tests first\n2. Implement minimal code to pass\n3. Refactor while keeping tests green\n\nSee [CLAUDE.md](CLAUDE.md) for development guidelines.\n\n### Development Workflow\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Write tests for your changes\n4. Implement the feature\n5. Ensure tests pass (`make test`)\n6. Run linter (`make lint`)\n7. Commit your changes (`git commit -m 'Add amazing feature'`)\n8. Push to the branch (`git push origin feature/amazing-feature`)\n9. Open a Pull Request\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/tomblanc/stromboli/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/tomblanc/stromboli/discussions)\n\n## Related Projects\n\n- [Pinocchio](https://github.com/tomblanc/pinocchio) - Docker-based alternative\n- [Claude Code](https://claude.ai/claude-code) - Official Claude CLI tool\n- [n8n](https://n8n.io/) - Workflow automation (see [VISION.md](docs/VISION.md) for integration)\n\n## Acknowledgments\n\nBuilt with:\n- [Gin](https://github.com/gin-gonic/gin) - HTTP web framework\n- [Podman](https://podman.io/) - Container engine\n- [Claude AI](https://claude.ai/) - AI assistant\n- [Prometheus](https://prometheus.io/) - Monitoring and metrics\n\n---\n\n**Stromboli** - Because your CI/CD pipeline deserves an AI volcano 🌋\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomblancdev%2Fstromboli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomblancdev%2Fstromboli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomblancdev%2Fstromboli/lists"}