Skip to content

acq: allow choosing the HOST port for a published guest port at run/create time #334

Closed

Description

@mogul

Problem

A kit's neutral publishedPorts entry declares a guest port; acq/the backend chooses the host port. With no host: set, acq assigns a distinct ephemeral loopback host port per sandbox (good — parallel sandboxes don't collide). But there is currently no run-time way to pick a predictable host port without editing the kit's spec.yaml:

  • publishedPorts[].host is a static literal in spec.yaml (and pinning it there would make every sandbox from that kit collide on one host port — the opposite of what we want for parallelism).
  • There is no acq run / acq create flag or env var that overrides the host mapping. ACQ_EXTRA_KITS is the only documented host→acq env var, and it selects kits, not ports.

Why --env doesn't solve it

A natural guess is acq run --env PASEO_PORT=6868. That doesn't work for this need, for two reasons:

  1. It would target the guest bind (e.g. Paseo's PASEO_LISTEN), not the host mapping. The thing users want to vary for parallel access is the host port.
  2. Even moving the guest port that way is a dead end: publishedPorts[].guest is a literal YAML scalar with no env interpolation in the translate step, so acq would still publish the original guest port and the mapping would miss the moved daemon.

So the capability actually needed is a run-time HOST-port override, not a guest-env override.

Concrete use case

The Paseo acq mixin kit (agentic-coding-patterns) serves a web UI on guest 6767. Running several Paseo sandboxes in parallel works today (each gets a different ephemeral host port), but users can't say "this sandbox's UI should be reachable at host 6868, that one at 6869" at launch time without hand-editing the spec. See:

Proposed capability (acq-internals + neutral surface)

A run-time host-port override that maps to the backend's native -p HOST:GUEST (create-time publish, guest-IP path — not the post-hoc msb ssh serve + ssh -L loopback tunnel, which would bypass the guest-IP transport). Possible shapes, in rough order of preference:

  1. acq create/run --publish HOST:GUEST (repeatable) — explicit, mirrors the existing post-hoc acq ports --publish verb and the backend -p.
  2. A host env var (e.g. ACQ_PUBLISH="6868:6767" or per-name) for scripted/parallel launches.

Guest bind stays whatever the kit sets (e.g. PASEO_LISTEN=0.0.0.0:6767); only the host side of the mapping is chosen at run time.

Acceptance notes

  • Must use the create-time publish path (guest network IP), matching the reachability the kit's 0.0.0.0 bind is designed for; explicitly should not silently fall back to the ssh -L/loopback post-hoc path.
  • Should compose with kits that declare publishedPorts without a host: (override the ephemeral choice, don't require the kit to pin host:).
  • Parallel sandboxes should each be able to specify their own host port.

Related downstream limitation (paseo kit verify)

The paseo kit's scripts/verify step 5b tests real host→guest reachability over the actual, ephemeral host port it reads back from acq ports (not a hardcoded 6767). But because acq picks that host port and can land on 6767, when a developer already runs their own Paseo daemon on host 6767 the two collide: acq's create-time -p can't own the contended port and the host fetch hits the wrong process. Today the verify script can only detect and SKIP that case (it deliberately refuses the acq ports --publish fallback, since that ssh--L path reaches guest loopback and wouldn't exercise the guest-IP transport under test).

A run-time host-port override (this issue) would let the verify script request a known-free host port for the create-time publish and thus run 5b unconditionally — turning today's SKIP-on-collision into a real pass. So this feature also removes a test-coverage gap, not just a UX limitation.

Alternatives considered

  • Pin publishedPorts[].host in the kit spec — breaks parallelism (single fixed host port collides across sandboxes).
  • acq ports <sandbox> --publish HOST:GUEST (exists today) — works post-hoc, but it tunnels via msb ssh serve + ssh -L to guest loopback, so it's a different transport than create-time publish and requires a second command after create.

Activity

  1. mogul commented on Aug 20, 2026

    @mogul
    ContributorAuthor
    • acq ports <sandbox> --publish HOST:GUEST (exists today) — works post-hoc, but it tunnels via msb ssh serve + ssh -L to guest loopback, so it's a different transport than create-time publish and requires a second command after create.

    Because this workaround exists, I'm not inclined to put too much priority on this, but I thought I'd better capture it.

  2. added
    documentationImprovements or additions to documentation
    enhancementNew feature or request
    and removed
    documentationImprovements or additions to documentation
    on Aug 20, 2026
  3. basiliskus commented on Sep 28, 2026

    @basiliskus
    Contributor

    The premise above doesn't match current acq: with no host:, the msb adapter defaults host to guest (acq.backends/msb.sh _acq_msb_port_flags_into: "host defaults to guest"), so every Paseo sandbox requests host 6767. Reproduced on acq main@187aa57 with msb 0.7.3: two Paseo sandboxes, both acq ports report 6767 -> host 127.0.0.1:6767, and only the first-started one owns the port. The second starts without any error, and its UI is unreachable; localhost:6767 serves the other sandbox's Paseo. So parallel Paseo sandboxes collide silently today. Could the adapter allocate a free loopback port when host: is omitted, or at least fail loudly when the host port is taken?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions