Files
headquarter/openspec/explorations/home-path-expansion.md
T
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

3.6 KiB

Exploration: ~ / $HOME Expansion in Mount Paths

User Request

Allow ~ and $HOME in mount paths for both regular mounts and git mounts.

Where This Applies

Container target paths (where it makes sense)

  • Regular mounts (mount.target): The absolute path inside the container where files are bind-mounted
  • Git mount mappings (mapping.target_path): The absolute path inside the container where repo subdirectories are mounted

Where it does NOT apply

  • Regular mount file paths (mount.files keys): These are relative to the mount target
  • Git mount source paths (mapping.source_path): These are relative to the cloned repo
  • Host-side source paths: The API runs in a container; ~ on the host would mean the Docker host's home, which the API container cannot access

Complexity Assessment

The Core Problem

~ means "user's home directory". But whose home?

Context Home Directory Knowable at Mount Time?
API container /root or /app Yes
Target container (manifest, user=root) /root Yes (from manifest)
Target container (manifest, user=user) /home/user Yes (from manifest)
Target container (legacy tool type) Unknown No (assume /root)
Docker host /home/alex or similar No (API is containerized)

Docker Compose Reality Check

Docker Compose does not expand ~ or $HOME in volume targets. These are passed literally to the Docker daemon. So ~/workspace becomes a directory literally named ~ in the container root.

This means we must resolve the path ourselves before writing the compose file.

Design Options

Option A: Simple /root default (minimal change)

  • Replace ~ and $HOME with /root in all container target paths
  • Apply during compose modification and git mount resolution
  • Effort: ~30 min, ~20 lines
  • Pros: Dead simple, works for root-running containers (most legacy setups)
  • Cons: Wrong for pi-agent (runs as user, home /home/user)
  • For manifest-based tools: read user.name from manifest, compute home as /home/{name} or /root
  • For legacy tools: default to /root
  • Pass home_dir through the mount resolution pipeline
  • Apply expansion in apply_resolved_profile() and _resolve_git_mount_mappings()
  • Effort: ~2 hours, touches 3-4 files
  • Pros: Correct for all container types
  • Cons: Slightly more plumbing

Option C: Configurable home per profile

  • Add home_directory field to ConfigProfile
  • User can override the container home directory
  • Effort: ~3 hours, schema change
  • Cons: Overkill, clutters UI

Recommendation

Option B — manifest-aware expansion. The pi-agent manifest already declares user.name, so we can compute the correct home directory. For backward compatibility, legacy tool types default to /root.

Files to Touch

  1. apps/api/src/services/config_profile_resolver.py — add expand_container_path() helper
  2. apps/api/src/api/tool_instances.py — pass home_dir to apply_resolved_profile() and git mount functions; determine home from manifest/tool type
  3. apps/api/src/services/manifest_compiler.py — expose helper to extract user from manifest
  4. Tests for expansion logic

Risks

Risk Mitigation
Wrong home for custom containers Document that manifest should declare user.name
$HOME env var not set in container We resolve it at compose generation time, so no runtime dependency
Breaking existing profiles with literal ~ in path Very unlikely; we can add an escape hatch if needed