Files
Alex Blank 29a12bb102 feat: expand ~ and $HOME in mount target paths
- Add expand_container_path() helper that resolves ~/ and $HOME/ prefixes
- Add get_manifest_home_dir() to compute /home/{user.name} or /root from manifest
- Set ENV HOME=... and ENV USER=... in generated Dockerfile for runtime compatibility
- Pass home_dir through instance creation and startup pipeline
- Expand mount targets in apply_resolved_profile() for regular profile mounts
- Expand mapping targets in _resolve_git_mount_mappings() for git mounts
- Expand working_directory and volume targets in _modify_compose_file()
- Update _prepare_manifest_instance to return home_dir alongside image tag
- Fetch tool_type early in start_instance to determine home_dir before profile application

Quality gates: pytest 188 passed, frontend typecheck clean

Addresses: home-path-expansion
2026-05-29 00:01:04 +02:00

2.9 KiB

Design: ~ / $HOME Expansion in Mount Paths

Architecture

New Helpers

expand_container_path(path: str, home_dir: str) -> str

Located in config_profile_resolver.py (or new shared module).

def expand_container_path(path: str, home_dir: str) -> str:
    if path.startswith("~/"):
        return os.path.join(home_dir, path[2:])
    if path == "~":
        return home_dir
    path = path.replace("$HOME/", home_dir + "/")
    path = path.replace("$HOME", home_dir)
    return path

get_manifest_home_dir(manifest: dict) -> str

Located in manifest_compiler.py.

def get_manifest_home_dir(manifest: dict) -> str:
    user = manifest.get("user")
    if user and user.get("name"):
        return f"/home/{user['name']}"
    return "/root"

get_tool_home_dir(tool_type: ToolType, manifest: dict | None) -> str

Located in tool_instances.py or manifest_compiler.py.

def get_tool_home_dir(tool_type: ToolType, manifest: dict | None = None) -> str:
    if tool_type.definition_type == "manifest" and manifest:
        return get_manifest_home_dir(manifest)
    return "/root"

Pipeline Changes

create_instance flow

  1. Determine home_dir from tool type + manifest (if manifest-based)
  2. Pass home_dir to _modify_compose_file() — expand mount targets in compose

start_instance flow

  1. Determine home_dir from tool type + resolved manifest
  2. Pass home_dir to apply_resolved_profile() — expand profile mount targets
  3. Pass home_dir to _resolve_git_mounts() — expand git mount mapping targets

apply_resolved_profile()

def apply_resolved_profile(
    instance_dir: str,
    resolved: ResolvedProfile,
    home_dir: str = "/root",
) -> tuple[...]:
    ...
    for mount in resolved.mounts.values():
        target = expand_container_path(mount.target, home_dir)
        ...

_resolve_git_mount_mappings()

def _resolve_git_mount_mappings(
    repo_path: str,
    mappings: list[dict],
    working_directory: str | None,
    home_dir: str = "/root",
) -> list[dict]:
    ...
    final_target = expand_container_path(target_path, home_dir)
    ...

Dockerfile Change

In compile_dockerfile(), after user creation, set HOME:

if user:
    home = f"/home/{user['name']}"
    lines.append(f"ENV HOME={home}")
    lines.append(f"ENV USER={user['name']}")

File Changes

File Change
apps/api/src/services/config_profile_resolver.py Add expand_container_path(), apply in apply_resolved_profile()
apps/api/src/services/manifest_compiler.py Add get_manifest_home_dir(), set HOME/USER env in Dockerfile
apps/api/src/api/tool_instances.py Determine home_dir, pass through all mount resolution functions
apps/api/tests/unit/test_home_path_expansion.py New unit tests
apps/api/tests/unit/test_manifest_compiler.py Add tests for get_manifest_home_dir and Dockerfile HOME env