Skip to content

Scoping: drive mimolette builds from a Claude Code session on asiago (tool locality, not remote terminal) #71

Open

Description

@twistedmelonman

Problem

mimolette.local is the designated macOS development server: an Apple Silicon
Mac Mini with materially better specs than the daily-driver MacBook Air
(asiago). The need for that hardware is real and demonstrated — builds,
simulators, and toolchain work are meaningfully faster there.

But mimolette is effectively headless. Not literally — it has a display — but
using it directly requires switching keyboard/mouse, waking it for Synergy, or
launching Remote Desktop. Each is enough friction that in practice the machine
is not driven by hand, and ideally never would be.

App development on a headless server is hard. The obvious fix — mosh + tmux with
Claude Code running on mimolette — solves session persistence but creates a
worse problem: it relocates the human's environment to the wrong machine. If
mimolette-CC decides to open a browser, it opens mimolette's browser. The
operator's accounts, browser sessions, clipboard, local files, and MCP
integrations (1Password, Chrome, etc.) all live on asiago, and a remote-terminal
architecture strands them.

Desired shape

Operator drives Claude Code on asiago. Local environment stays local:
browser, accounts, clipboard, personal files, local MCP servers. Work requiring
the Mini's hardware executes on mimolette, which installs and uses whatever
tools it needs but never requires a direct hand on its keyboard.

Framed precisely: this is a tool-locality problem, not a session-persistence
problem. The goal is not a remote terminal. It is a controller on asiago whose
reach extends to mimolette.

Goals

  • Operator interacts with a Claude Code session running on asiago.
  • Browser, credentials, clipboard, and local MCP servers remain on asiago.
  • Hardware-heavy execution (builds, simulators, Xcode, EAS, Android SDK) happens
    on mimolette.
  • Long-running remote work survives the operator closing the laptop lid.
  • mimolette requires no attached input devices under normal operation.

Non-goals

  • Replacing mosh/tmux access to mimolette for genuine interactive admin work.
    That path stays available; it is simply not the primary development workflow.
  • Running the operator's browser or credential store on mimolette.
  • Tunneling / Tailscale / off-LAN access. Explicitly deferred. Everything
    below assumes both machines are on the same network. Remote access is a
    well-understood addition that does not alter the architectural choice.
  • Any change to the existing OP_SERVICE_ACCOUNT_TOKEN ssh-forwarding design
    (see CLAUDE.md) unless Open Question 2 forces it.

Explicitly rejected: two conversational Claudes

An early framing was "Claude Code on asiago talks to Claude Code on mimolette."
Rejecting that as the primary architecture:

  • Both agents would hold substantially the same context, one of them badly.
  • Every hop between them is a natural-language bottleneck where context is
    summarized and lost.
  • Failures surface as one model's paraphrase of an error rather than the error.

Two agents earn their cost when they hold different context — e.g. a
controller holding operator intent, dispatching a slow build to a worker whose
only job is to babysit it. That narrow case is Option C below.


Established environment

Verified, not assumed. Details in the Hardware appendix.

asiago already SMB-mounts mimolette's workspace. All 22 working repos are
reachable at /Volumes/Workspaces on asiago. This means native Read / Edit /
Grep / Write operate on the real files from asiago — no ssh cat, no dual
checkout, no sync boundary, single source of truth.

Path translation is pure string substitution, requiring no lookup table or
configuration:

Side Path
asiago (SMB client) /Volumes/Workspaces/<repo>
mimolette (canonical) /Volumes/extra-vieille/Workspaces/<repo>
mimolette (symlink) ~/Developer/<repo>

Convention: prefer the canonical path over the ~/Developer symlink in
scripted ssh commands. Some toolchains resolve symlinks and report canonical
paths in output; pinning avoids logs that disagree with the invoked directory.

Consequence for the architecture choice: remote file access is already
solved by existing infrastructure. What remains to be solved is remote
execution.


Candidate architectures

Option A — Local CC + ssh executor (zero infrastructure) — leading

Claude Code runs on asiago. Files are edited natively over the existing SMB
mount. Remote execution goes over ssh mimolette '...'. Long builds launch into
a detached tmux on the Mini and are polled for status.

  • Pros: nothing to build; preserves the existing ssh credential flow exactly;
    browser and MCP servers stay local by construction; file access already works.
  • Cons: no structured tool schemas (the agent must recall invocation
    conventions); no permission granularity — ssh-via-bash is all-or-nothing.
  • Why it leads: the SMB mount removes the strongest argument for Option B.

Option B — MCP server on mimolette

mimolette runs an MCP server exposing build/test/exec capabilities. asiago-CC
connects over an ssh tunnel.

  • Pros: structured tools with real schemas; per-tool permissioning; errors
    surface verbatim.
  • Cons: real implementation and maintenance cost. Primary risk: an agent
    driving a remote box tends to want an arbitrary shell more than a few curated
    verbs. If the server collapses into exec(cmd), this is ssh with more moving
    parts and strictly more failure modes.
  • Gating test: can 3–5 specific, recurring operations be named that cover
    most remote traffic? Since SMB already handles file access, the remaining scope
    is essentially build execution — the probable answer is one or two
    operations
    , which argues against building this. Experiment 1 tests that.

Option C — Remote Control / SendMessage peer

A persistent CC session on mimolette registers as an addressable peer; asiago-CC
dispatches via SendMessage.

  • Status: entirely untested. See Open Question 1.
  • Pros: native mechanism, nothing to build. Good fit for fire-and-forget
    dispatch ("run the build, notify when done").
  • Cons: does not solve persistence — sessions register while alive and go
    offline when they end, so keeping a peer available still means keeping a
    session alive (tmux). Reply direction unverified.

Option D — Agent SDK server on mimolette

A long-lived process wrapping the Claude Agent SDK, exposing a session over
HTTP/websocket, with asiago as a thin client.

  • Assessment: buildable and genuinely designed for this, but requires
    reimplementing session management, auth, streaming, tool permission prompts,
    and interrupt handling. Not warranted unless A, B, and C all fail against a
    specific articulable need.

Open design questions

1. Does a mimolette CC session appear as an addressable peer from asiago?

Untested. A prior ListAgents run from asiago showed ~70 peers, but every
Remote Control entry is a phone-attached session — an established,
frequently used workflow. mimolette has never been used as a Remote Control
peer, so no inference about machine-to-machine peering can be drawn from that
history.

Test: start CC on mimolette inside tmux over ssh, then from asiago:

  1. Does the session appear as idle rather than offline?
  2. Does SendMessage to it produce any effect?
  3. Does a reply return to the dispatching session, or land only in the peer's
    own transcript?

Question 3 is decisive for Option C. Bidirectional replies make it a real
controller/worker split with zero infrastructure. Dispatch-only reduces it to a
job runner — still useful, much narrower.

2. Credential flow for any non-ssh listener

Per CLAUDE.md, the target deliberately does not store OP_SERVICE_ACCOUNT_TOKEN
in its Keychain; the token arrives via the dev machine's ssh wrapper (SendEnv)
and target AcceptEnv. The existing note records "no current use case" for
non-ssh sessions having it.

A boot-started MCP server (Option B) or persistent peer (Option C) is exactly
that use case.
Either would require revisiting the decision — Keychain on
target, or accepting the listener cannot reach 1Password. Option A sidesteps
this entirely
by preserving ssh-session semantics, a further point in its
favor.

3. What actually needs to run remotely?

Unquantified. Builds and simulators clearly. Less clear: test runs, linting,
dependency installs, git operations. The answer determines whether remote
traffic is a few coarse heavy operations (viable for B) or continuous
fine-grained chatter (favors A). Experiment 1 answers this.

4. Does SMB editing interfere with concurrent builds?

Editing over SMB while a build runs on the far side is a cache-coherence
question, not only a latency one. Xcode's build system and any file-watchers on
mimolette read files an SMB client on asiago is concurrently writing. Usually
fine, but can produce stale reads or partially-visible writes surfacing as
inexplicable build failures.

Not expected to block. Recorded so it is treated as a prime suspect rather than
diagnosed from scratch. Watch during Experiment 1.


Experiments

Experiment 1 — friction log (one real work session, nothing built).
Work a genuine task in asiago-CC: edit via /Volumes/Workspaces, dispatch builds
over ssh. Record every point of awkwardness. That list is the candidate tool
schema for Option B
— and if it reads as "it just wanted a shell," Option B is
disconfirmed and Option A stands. Also answers Open Questions 3 and 4.

Experiment 2 — benchmark the premise.
Time an identical real build on asiago (internal NVMe) vs. mimolette (USB 3.2
Gen 2 bridged NVMe). Tests whether the Mini's CPU advantage survives its storage
handicap. Expected outcome is "yes"; this establishes the baseline.

Experiment 3 — peer addressability (~10 min, nothing built).
Resolves Open Question 1 and settles Option C outright. Cheap, but lower priority
than 1 and 2 — Option A's viability rises considerably if SMB-edit plus ssh-build
proves comfortable.

Success criteria

An architecture is adopted when, over a real development session:

  • The operator never switches input to mimolette.
  • Browser and credential operations resolve on asiago without special handling.
  • A long build survives closing the laptop lid and its result is retrievable.
  • Remote invocation friction is low enough not to prompt a fallback to
    mosh+tmux.

Status

Scoping only. No implementation committed. Current leaning is Option A —
SMB for files, ssh for execution, nothing built — pending Experiment 1.
Graduates to a docs/plans/ document once the experiments resolve the open
questions.


Appendix: hardware findings

Verified via diskutil, ioreg, system_profiler, and vendor specifications.
None of this affects the architecture choice — the storage path is identical
under all four options. It bears on the premise that mimolette is materially
better for build work.

Storage

  • Volume: extra-vieille, 2TB APFS, 12G used by Workspaces
  • Media: NVMe SSD (user-supplied) in the integrated slot of a
    UGREEN Mac mini M4 Dock
  • Transport: USB-to-NVMe bridge → USB 3.2 Gen 2 (10 Gb/s), ~1 GB/s
    practical sequential
  • Host connection: "Dual USB-C Host Cable" — two USB-C plugs in one molded
    housing, both USB
  • Thunderbolt: all three Mini ports report No device connected — 120
    Gb/s of aggregate bandwidth unused
  • Contents: Workspaces (22 repos), Caches, Simulators, Android — the
    complete build working set

Note: the dock's "NVMe SSD support" describes the media, not the transport.
The drive is genuinely NVMe but reaches the Mac through a USB bridge, not PCIe —
diskutil reports Protocol: USB. Easy to misread as implying a PCIe path.

Assessment

10 Gb/s is the top of the USB 3.x range. Sequential throughput is comfortably
adequate for compilation — a Swift build does not approach 1 GB/s sequential
read. The residual concern is per-operation latency through the USB bridge,
which accumulates via operation count rather than presenting as a bandwidth
ceiling. This is Xcode's access pattern, most acutely on incremental builds.

Relevant comparison:

Path Transport Practical ceiling
Current NVMe → USB bridge → USB 3.2 Gen 2 ~1 GB/s
Thunderbolt/USB4 enclosure NVMe → PCIe ~3 GB/s
Mini internal NVMe → PCIe ~3–5 GB/s

A Thunderbolt 4 / USB4 NVMe enclosure on any unused port would remove the bridge
entirely. Deprioritized — at 10 Gb/s the current path is unlikely to be the
binding constraint. Revisit only if Experiment 2 shows builds are I/O-bound.

Tooling note

system_profiler SPUSBDataType exits rc=0 with zero bytes and empty stderr
in a non-interactive ssh session — a clean success producing nothing. Any future
target-side automation shelling out to system_profiler may silently receive an
empty string rather than an error. ioreg and diskutil work correctly over
ssh
and are the reliable substitutes.

Activity

  1. twistedmelonman commented on Oct 1, 2026

    @twistedmelonman
    MemberAuthor

    2026-10-01 decision: Mimolette is also the end-state CI build machine. Interim step: the full suites run once, in CI, as required checks (claude-config#664, dotfiles#387).

    Not started. Next: a self-hosted runner, with fork-PR approval on public repos, and caffeinate -i around jobs.

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 requestquestionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions