Skip to content
Back to skills

2933 Dc 008 Auto Detect Launcher 89208474

ASecurity

**Level**: 3 | **Critical Path**: No | **Estimate**: 20 min **Dependencies**: DC-006

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
devopspythonbashdocker

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2933-dc-008-auto-detect-launcher_89208474 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2933 Dc 008 Auto Detect Launcher 89208474?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2933 Dc 008 Auto Detect Launcher 89208474
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2933-dc-008-auto-detect-launcher-89208474/badge)](https://www.skillsdirectory.com/skills/tools-only-2933-dc-008-auto-detect-launcher-89208474)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# DC-008: Add Auto-Detect Launcher Mode in Orchestrator

**Level**: 3 | **Critical Path**: No | **Estimate**: 20 min
**Dependencies**: DC-006

## Objective

Update `_create_launcher()` in `zerg/orchestrator.py` to auto-detect the appropriate launcher:
- Use ContainerLauncher if `.devcontainer/devcontainer.json` exists AND Docker image is built
- Otherwise use SubprocessLauncher
- Config override takes precedence

## Files Owned

- `zerg/orchestrator.py` (modify)

## Files to Read

- `zerg/launcher.py` (ContainerLauncher.docker_available, image_exists)
- `zerg/config.py` (WorkersConfig.launcher_type)

## Implementation

Update `_create_launcher()` method:

```python
from zerg.launcher import ContainerLauncher, LauncherConfig, LauncherType, SubprocessLauncher, WorkerLauncher


def _create_launcher(self) -> WorkerLauncher:
    """Create worker launcher based on config and environment.

    Priority:
    1. Explicit config override (subprocess or container)
    2. Auto-detect based on devcontainer presence and image availability

    Returns:
        Configured WorkerLauncher instance
    """
    # Get configured launcher type
    configured_type = self.config.workers.launcher_type

    # Build launcher config
    launcher_config = LauncherConfig(
        timeout_seconds=self.config.workers.timeout_minutes * 60,
        log_dir=Path(self.config.logging.directory),
    )

    # Check for explicit override
    if configured_type == "subprocess":
        logger.debug("Using SubprocessLauncher (explicit config)")
        launcher_config.launcher_type = LauncherType.SUBPROCESS
        return SubprocessLauncher(launcher_config)

    if configured_type == "container":
        logger.debug("Using ContainerLauncher (explicit config)")
        launcher_config.launcher_type = LauncherType.CONTAINER
        return ContainerLauncher(launcher_config)

    # Auto-detect mode
    return self._auto_detect_launcher(launcher_config)


def _auto_detect_launcher(self, config: LauncherConfig) -> WorkerLauncher:
    """Auto-detect appropriate launcher based on environment.

    Args:
        config: Launcher configuration

    Returns:
        SubprocessLauncher or ContainerLauncher
    """
    # Check for devcontainer
    devcontainer_path = self.repo_path / ".devcontainer" / "devcontainer.json"

    if not devcontainer_path.exists():
        logger.debug("No devcontainer found, using SubprocessLauncher")
        config.launcher_type = LauncherType.SUBPROCESS
        return SubprocessLauncher(config)

    # Check Docker availability
    if not ContainerLauncher.docker_available():
        logger.warning("Devcontainer exists but Docker not available, using SubprocessLauncher")
        config.launcher_type = LauncherType.SUBPROCESS
        return SubprocessLauncher(config)

    # Check if image is built
    if not ContainerLauncher.image_exists("zerg-worker"):
        logger.info("Devcontainer exists but image not built, using SubprocessLauncher")
        logger.info("Run 'zerg init --with-containers' to build the image")
        config.launcher_type = LauncherType.SUBPROCESS
        return SubprocessLauncher(config)

    # All conditions met for container mode
    logger.info("Using ContainerLauncher (auto-detected)")
    config.launcher_type = LauncherType.CONTAINER
    return ContainerLauncher(config)


def get_launcher_mode(self) -> str:
    """Get the current launcher mode.

    Returns:
        'subprocess', 'container', or 'auto'
    """
    if isinstance(self.launcher, ContainerLauncher):
        return "container"
    return "subprocess"
```

Also add a method to check if container mode is available:

```python
def container_mode_available(self) -> tuple[bool, str]:
    """Check if container mode can be used.

    Returns:
        Tuple of (available, reason)
    """
    devcontainer_path = self.repo_path / ".devcontainer" / "devcontainer.json"

    if not devcontainer_path.exists():
        return False, "No .devcontainer/devcontainer.json found"

    if not ContainerLauncher.docker_available():
        return False, "Docker is not available or not running"

    if not ContainerLauncher.image_exists("zerg-worker"):
        return False, "Docker image 'zerg-worker' not built (run zerg init --with-containers)"

    return True, "Container mode available"
```

## Verification

```bash
python -c "
from zerg.orchestrator import Orchestrator
from zerg.config import ZergConfig
from zerg.launcher import SubprocessLauncher, ContainerLauncher

# Test with default config (should auto-detect)
config = ZergConfig()
orch = Orchestrator('test-feature', config)

print(f'Launcher type: {type(orch.launcher).__name__}')
print(f'Mode: {orch.get_launcher_mode()}')

available, reason = orch.container_mode_available()
print(f'Container mode available: {available}')
print(f'Reason: {reason}')
"
```

## Acceptance Criteria

- [ ] _create_launcher() checks explicit config first
- [ ] Auto-detect checks devcontainer.json existence
- [ ] Auto-detect checks Docker availability
- [ ] Auto-detect checks image existence
- [ ] Falls back to subprocess if any condition fails
- [ ] get_launcher_mode() returns current mode
- [ ] container_mode_available() returns availability + reason
- [ ] Proper logging for mode selection
- [ ] No ruff errors: `ruff check zerg/orchestrator.py`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.