Skip to content

feat: Container-based isolation for safe autonomous execution#876

Draft
acreeger wants to merge 6 commits intomainfrom
feat/issue-332__container-based-isolation
Draft

feat: Container-based isolation for safe autonomous execution#876
acreeger wants to merge 6 commits intomainfrom
feat/issue-332__container-based-isolation

Conversation

@acreeger
Copy link
Copy Markdown
Collaborator

@acreeger acreeger commented Mar 3, 2026

Fixes #332

feat: Container-based isolation for safe autonomous execution

Overview

Add optional container-based isolation for looms, enabling safer bypassPermissions usage and allowing users to define complex multi-service environments (Redis, databases, multiple servers) without iloom needing to understand each service.

Value Proposition

Today With Container Isolation
bypassPermissions executes on host Execution sandboxed to container
iloom needs service-specific code Users define their own environments
Risk scales with autonomy Damage contained, nuke container if needed
Single port calculation (web) User-defined ports for any service

Core Concept

iloom provides:

  • Worktree isolation (existing)
  • Port offset calculation for user-defined services
  • Container lifecycle management
  • Environment variable injection

User provides:

  • devcontainer.json / docker-compose.yml defining their services
  • Uses ILOOM_PORT_<NAME> convention for port variables

Port Discovery & Configuration

Convention

Users use ILOOM_PORT_<NAME> prefix in their compose files:

services:
  web:
    ports:
      - "${ILOOM_PORT_WEB}:3000"
  api:
    ports:
      - "${ILOOM_PORT_API}:4000"
  redis:
    ports:
      - "${ILOOM_PORT_REDIS}:6379"

During il init

iloom parses compose file, finds ILOOM_PORT_* vars, prompts for base ports:

Detected container configuration...
Found port variables: ILOOM_PORT_WEB, ILOOM_PORT_API, ILOOM_PORT_REDIS

What's the base port for WEB? › 3000
What's the base port for API? › 4000  
What's the base port for REDIS? › 6379

Settings

{
  "container": {
    "enabled": true,
    "ports": {
      "WEB": 3000,
      "API": 4000,
      "REDIS": 6379
    }
  }
}

At il start 123

iloom calculates offsets and writes to .env:

ILOOM_PORT_WEB=3123
ILOOM_PORT_API=4123
ILOOM_PORT_REDIS=6502

Proposed Flow

il start 123
  → Create worktree (existing)
  → Calculate port offsets, write to .env
  → Launch devcontainer with worktree mounted
  → Claude Code runs INSIDE container
  → bypassPermissions is now sandboxed

il finish 123
  → Generate summary (existing)
  → Stop/remove container
  → Merge worktree (existing)

Configuration

{
  "container": {
    "enabled": true,
    "configPath": ".devcontainer/devcontainer.json",
    "ports": {
      "WEB": 3000,
      "API": 4000
    },
    "keepAlive": false  // Stop container on finish vs keep running
  },
  "workflows": {
    "issue": {
      "permissionMode": "bypassPermissions"  // Now safe!
    }
  }
}

Open Questions

Claude Code Execution

  • How does Claude Code CLI run inside the container?
  • Option A: Install Claude CLI inside container, run natively
  • Option B: Run Claude on host, exec commands into container
  • Option C: Use devcontainer's remote execution capabilities
  • Needs research: How does devcontainer exec interact with Claude's terminal sessions?

IDE Integration

  • How does --ide cursor work with devcontainers?
  • VS Code has "Reopen in Container" - should iloom trigger this?
  • Or does iloom open the worktree and let user reopen in container manually?
  • Different IDEs handle devcontainers differently (WebStorm, etc.)

Container Lifecycle

  • Start on il start, stop on il finish?
  • What if user runs il spin multiple times - reuse running container?
  • What about il cleanup - force remove container?
  • Resume after machine restart?

Parsing Strategy

  • Parse devcontainer.json or docker-compose.yml or both?
  • What if both exist with different port definitions?
  • What if neither exists but container.enabled: true?

Database Integration

  • How does this interact with Neon branching?
  • If user runs containerized Postgres, do they still want Neon?
  • Support both? (containerized services + Neon for prod-like data)

Secrets & Environment

  • How do API keys (Linear, etc.) get into the container?
  • Mount .env.local? Copy? Inject via env?
  • Security implications of mounting secrets into container

Filesystem Mounting

  • Mount worktree as volume
  • What about node_modules - mount or install inside?
  • .git directory handling
  • Volume mounts for data persistence across container restarts

Network Isolation

Risks

  1. Complexity - Significant feature touching many parts of iloom (init, start, finish, spin, cleanup, open, dev-server)

  2. Docker dependency - Not all users have/want Docker. Must remain optional with graceful degradation.

  3. Performance overhead - Container startup adds latency to il start. Image pull on first run. Need to quantify.

  4. Platform inconsistencies - Docker behavior differs across macOS/Linux/Windows. Docker Desktop licensing considerations.

  5. Resource usage - Multiple running containers (one per loom) could exhaust memory/CPU. May need guidance on limits.

  6. Debugging difficulty - Container issues are harder to diagnose than host issues. Need good error messages.

  7. devcontainer CLI dependency - Requires @devcontainers/cli installed. Add to iloom dependencies or require user install?

  8. Breaking existing workflows - Users with existing devcontainer setups may have conflicts. Migration path needed.

Non-Goals (V1)

  • Remote container execution (Docker on remote host)
  • Kubernetes/orchestration support
  • Multi-container networking between looms
  • Container image building/publishing

Implementation Approach

Suggest implementing in waves:

Wave 1: Foundation

  • Port parsing during il init
  • Port calculation and .env injection at il start
  • Basic devcontainer launch/stop

Wave 2: Integration

  • IDE integration (open in container)
  • il spin inside container
  • il open / il dev-server with containers

Wave 3: Polish

  • il cleanup container handling
  • Error handling and recovery
  • Documentation

Acceptance Criteria

  • Users can define multi-service environments via devcontainer
  • il init detects and configures port mappings
  • il start launches container with correct ports
  • Claude Code can execute inside container
  • bypassPermissions is sandboxed to container
  • il finish cleans up container
  • Graceful fallback when Docker unavailable
  • Works with existing Neon integration (or clearly documented alternative)

This PR was created automatically by iloom.

- Add `parseComposeFile()` to extract port mappings from docker-compose.yml
- Add `generateOverrideFile()` to write override files with offset host ports
- Export `ComposePortMapping` type with service, hostPort, containerPort, protocol, hostIp
- Handle short syntax, IP-bound syntax, long-form syntax, protocol variants
- Preserve host_ip bindings in generated overrides to prevent unintended 0.0.0.0 exposure
- Skip port ranges (V1 scope) and container-only entries
- Throw on non-numeric identifier to prevent NaN propagation
- Handle port wrap-around via wrapPort() for ports exceeding 65535
- Add yaml@2.8.2 dependency for YAML parsing and serialization
- Add 30 tests covering all port formats, edge cases, and security scenarios
@acreeger acreeger force-pushed the feat/issue-332__container-based-isolation branch from 86d2d4b to 9c0808a Compare March 3, 2026 23:57
acreeger added 5 commits March 3, 2026 18:59
…er dev server suggestion

- Add detectComposeFile() to src/utils/docker.ts supporting compose.yaml, compose.yml,
  docker-compose.yaml, docker-compose.yml (priority order per Docker docs)
- Parse compose services and port mappings (short/long syntax, IP:HOST:CONTAINER, string published)
- Rethrow unexpected errors; only suppress YAMLException for malformed YAML
- Pass HAS_COMPOSE_FILE, COMPOSE_FILE_NAME, COMPOSE_SERVICES_INFO template variables in init
- Add compose detection question to init-prompt.txt suggesting docker dev server mode
- Track compose_detected boolean in init.completed telemetry
- Add 18-test suite covering all file variants, port syntaxes, and edge cases
- Add js-yaml runtime dependency for YAML parsing
…orkflows

- Add compose management methods to DockerManager: buildComposeProjectName,
  getComposeOverrideDir, getComposeOverridePath, hasComposeOverrideFile,
  isComposeStackRunning, teardownComposeStack, removeComposeOverrideFile
- Update terminateDevServer to check for compose override file and tear down
  compose stack before falling back to single-container cleanup
- Add Step 1.6 to cleanupWorktree to remove compose override files from
  the iloom data directory in docker mode (non-fatal)
- Add 'compose-override' to OperationResult.type union
- Add 9 new tests covering compose teardown in terminateDevServer and cleanupWorktree
…ction

When devServer is set to 'docker', DevServerManager now auto-detects
compose files (compose.yml, compose.yaml, docker-compose.yml,
docker-compose.yaml) in the worktree before falling back to
Dockerfile-based strategy.

- Add ComposeDevServerStrategy: start/stop/status for docker compose
  stacks, port readiness via TCP probe, signal forwarding, override
  file lifecycle, project naming as iloom-{identifier}
- Add findComposeFile() utility: checks compose file candidates in
  preference order (compose.yml first)
- Update DevServerManager to inject ComposeUtils and auto-detect
  compose files in ensureServerRunning, runServerForeground,
  isServerRunning, and cleanup
- Compose override directory is created on demand and override files
  are cleaned up on stack teardown
- Running compose stacks tracked by project name (not port) to avoid
  key collision on retry
- TCP probe uses 1-second socket timeout to avoid blocking on
  firewalled ports
- Full test coverage: ComposeDevServerStrategy.test.ts (30 tests),
  DevServerManager compose mode tests (20 tests)
- Fix TypeScript strict mode errors in compose.ts with undefined guards
- Unify override file naming between compose.ts and DockerManager.ts
- Deduplicate ComposePortMapping type definition
- Standardize compose file search order
- Consolidate on single yaml parsing library
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

feat: Container-based isolation for safe autonomous execution

1 participant