Skip to content

Generalize "lend my Mac" to a hands-node registry (macmini + rpi1 + ...) #27

Description

@chaodu-agent

Generalize "lend my Mac" → "lend a hands node" (macmini + rpi1 + …)

Problem

The reverse-attach design writes the tools-provider ("hands") as the Mac, everywhere:

  • ADR: "The Mac dials the pod", "the human decides which pod the Mac dials", "lend my Mac to this agent".
  • requirement: "lend my Mac to this", "macmini chooses the profile at dial time", POST /attach on the Mac's oab-instance-mcp.

But the strategic direction is Linux-first: the scalable "hands" are cheap Linux nodes (rpi1 now, more later), not a single expensive Mac. So "lend" must not be Mac-specific.

Proposal

Treat the hands side as a registry of hands nodes, each running an instance-mcp (macmini = Swift; rpi1 = the Rust port, #15). The lend action becomes:

"Lend a hands node to this session" → pick a session, then pick a node (macmini / rpi1 / …) + profile + TTL.

The selected node dials the pod and lends its tools:

So a session gets two (soon N) lend options, not one hard-coded Mac.

What this touches

  • UI (Connect/Remote): "lend my Mac" → a node picker (list of registered/online hands nodes).
  • Grant flow / POST /attach: the grant must name which node dials; the attach secret is minted for/handed to that node (today it is implicitly the Mac). The node then dials wss://<pod-tailnet>/tools/attach/<session> with the secret it holds.
  • Node registry / liveness: which hands nodes exist and are online; enough for the picker.
  • Identity: the ADR already hints at tailscale whois <src> tag-based identity for tagged nodes — a clean multi-node fit (each hands node is a tagged tailnet node), vs. today's "the Mac chooses the profile at dial time, nothing to look up".

Why now

Verified today (see #15): a Rust instance-mcp runs on rpi1 with MCP + sys_info + screenshot(grim) + auth gate, and the reverse-attach disposition state machine + attachURL have Rust↔Swift conformance parity (#24, 23/23). The remaining gap to a real "lend rpi1 to a session" is exactly this: (a) the WS transport (dial loop) on the node, and (b) a node-agnostic grant/lend flow so rpi1 can be the dialer, not just the Mac.

Concretely observed while trying to test end-to-end against a fresh session (kiro-4412): the pod's /tools/attach/{session} route is 404 until a grant exists — i.e. nothing can dial until a lend/grant is created, and today that creation is Mac-bound. That is the blocker this issue removes.

Scope note

This is a design/architecture issue (generalize the hands side); the security invariants stay the same (no egress from the sandbox; node dials the pod; verifier-only in the pod; per-connection tool profile). It refines, not replaces, the reverse-attach ADR.

Refs #15 (Rust Linux port), #24 (reverse-attach conformance), docs/adr/reverse-attach.md, docs/requirements/reverse-attach.md.

Activity

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