# Harness ops
How to inspect, install, and repair **this** runtime (agent + host pool). Use when tools fail,
hosts look wrong, or the user asks you to update `myco` / explain the harness.
## Host PATH prerequisites
Same executables as the README **Install** section (extra binaries on `PATH`). Install on each machine
that runs the agent and/or host tools; remotes need what their host tools spawn, not only the
agent laptop.
**Required**
- **`ssh`** — attaches remotes (`ssh … myco --mode host` over NDJSON) and is used for install/diagnose over SSH.
- **`lynx`** — powers the `lynx_tui_browser` host tool (`lynx -dump` plaintext pages / search results).
- **`uv`** — hermetic Python runs (agent computer-use norm: scripts and deps without polluting the system).
- **`bash`** — host `bash` tool (one-shot `exec` and multi-turn shell sessions).
**Recommended**
- **`git`** — worktrees/branches, repo inspection, and `git archive` when shipping local source to remotes.
- **`gh`** — GitHub CLI for PRs, issues, and release workflows the agent often drives.
- **`curl`** — `build.rs` MiniLM asset fetch at compile time, and downloading release source tarballs.
Also needed when **building from source**: stable **Rust / cargo** (and `curl` as above). Optional
`trunk` + `wasm32-unknown-unknown` only for **`crates/myco-gui`**.
## Finding configured hosts
- **Local** is always present (in-process); it is never configured.
- Remotes are the concrete `Host` aliases in **`~/.ssh/config`** (`Include`s are
followed; wildcard `*`/`?` and negated `!` patterns are ignored; alias `local`
is reserved). Host name == alias == SSH destination.
- **`~/.myco/config.toml`** (or `$MYCO_CONFIG` / `myco --config`) holds knobs only:
`enable_subagent`, `attach_timeout_secs`.
- Read `~/.ssh/config` with tools when you need remote names or SSH destinations.
- Tell the user to run **`/hosts`** for live attach status (local ok/in-process; remotes idle / ok / DOWN); you cannot run slash-commands.
- Host tool field `host` must match a configured name (`local` or a remote `name`). Omitted → `local`.
## Updating / installing `myco`
**Local** uses the agent process binary / in-process worker — rebuild/reinstall the interactive
`myco` on this machine and **restart the CLI**.
For **remotes**, prefer a **same-platform binary** (release asset or build on the target)
when you are not actively developing myco; only **build from a local git tree** when you are
working on the myco codebase itself (unreleased commits, dirty worktree, or a feature branch
that must ship). Embedding weights are **compiled into** `myco`, so a correct binary is enough to
run — you do **not** deploy model files next to it. Do **not** scp/rsync a prebuilt binary
across **mismatched** OS, CPU arch, or glibc (e.g. newer glibc → older cluster fails with
`GLIBC_X.Y not found`); for those targets, compile on the machine or use a matching release.
### Choose: release snapshot vs local source tree
1. **Inspect the running agent binary** (this process):
- `session_meta` with `action: "executable_path"` → absolute path of the agent `myco`.
- Then via bash: `"$path" --version` (package version from clap / `CARGO_PKG_VERSION`).
2. **If you are currently working on myco** (cwd is a myco checkout, or the user asked to
deploy local unreleased changes): build from that git tree (see **Snapshot the repo**
below) so remotes match the working tree.
3. **Otherwise** (normal install / update): download a **source snapshot from GitHub
Releases** for the version you want (usually the same as the local binary's
`--version`, or a newer release the user named):
```text
https://github.com/tsnl/myco/releases
```
Typical assets / URLs (GitHub):
```bash
# Prefer the release tag that matches (or is newer than) local `myco --version`.
# Source tarball for tag v0.1.0 (example):
VER=0.1.0
curl -fsSL -o /tmp/myco-src.tgz \
"https://github.com/tsnl/myco/archive/refs/tags/v${VER}.tar.gz"
# Or the auto "Source code (tar.gz)" asset on the release page for that tag.
```
Unpack on each remote and `cargo install` there (next section). If no suitable release
exists yet, fall back to archiving the local git tree.
### Snapshot the repo (local git tree only)
Use this when deploying **work-in-progress** or unreleased commits from a myco checkout.
From the myco git root, create a source snapshot with **`git archive`** (tree only — tracked
files at a commit/tree; not untracked files, and not uncommitted dirty work unless you archive a
commit that includes them):
```bash
# Clean committed snapshot of HEAD (usual case):
git archive --format=tar.gz -o /tmp/myco-src.tgz HEAD
# Include current dirty tracked changes: temporary tree object, then archive it:
REF=$(git stash create) # empty if worktree is clean — fall back to HEAD
git archive --format=tar.gz -o /tmp/myco-src.tgz "${REF:-HEAD}"
```
`git archive` is the right “tarball of this repo state” tool. Commit (or use `git stash create`)
first if the install must include uncommitted edits. Untracked files are never in the archive;
add/commit them if they are required to build.
### Embedding weights (MiniLM / Candle) — fully embedded in the binary
Semantic search bakes all-MiniLM-L6-v2 (Candle) into `myco` at **compile time**
(`build.rs` stages under `OUT_DIR` + `include_bytes!`). Runtime never reads weight
files and never downloads from Hugging Face.
| **Running / shipping** | The **`myco` binary only** for that OS/CPU/libc. No model pack, no `embed_weights/` on the target. |
| **Compiling from source** | Network so `build.rs` (`hf-hub`) can populate the shared Hub cache and stage into `OUT_DIR` (or seed via warm `HF_HOME` / `MYCO_EMBED_CACHE` / `src/text_search/embed_weights/`). |
Source tarballs / crates.io packages / `git archive` do not ship the ~87 MiB weight
files (gitignored; not part of the package). That only matters when **building**; a
finished binary already contains the weights. Details:
`src/text_search/embed_weights/README.md`.
Because weights are embedded, a **release only needs platform-matched binaries**. Do not scp
binaries across mismatched OS/arch/glibc; for those hosts, build there or use a matching
release asset.
### Install on each remote host (build from source)
```bash
HOST=devbox # Host alias from ~/.ssh/config (== myco host name)
# /tmp/myco-src.tgz is either a GitHub release source tarball or a local git archive.
scp -o BatchMode=yes /tmp/myco-src.tgz "$HOST:/tmp/myco-src.tgz"
ssh -o BatchMode=yes "$HOST" 'set -euo pipefail
rm -rf ~/src/myco-src ~/src/myco-src-extract
mkdir -p ~/src/myco-src-extract ~/.local/bin
tar -xzf /tmp/myco-src.tgz -C ~/src/myco-src-extract
rm -f /tmp/myco-src.tgz
# GitHub release tarballs nest under myco-<tag>/; `git archive` is usually flat.
entries=(~/src/myco-src-extract/*)
if [ ${#entries[@]} -eq 1 ] && [ -d "${entries[0]}" ]; then
mv "${entries[0]}" ~/src/myco-src
rmdir ~/src/myco-src-extract 2>/dev/null || rm -rf ~/src/myco-src-extract
else
mv ~/src/myco-src-extract ~/src/myco-src
fi
export PATH="$HOME/.cargo/bin:$PATH"
cargo install --path ~/src/myco-src --force --locked --root "$HOME/.local"
# ~/.local/bin is the usual remote install path in multi-host setups
~/.local/bin/myco --version
'
```
- Require **Rust/cargo** (and network once for `hf-hub` MiniLM assets, or a warm Hub cache) when building from source. Prefer a
prebuilt **same-platform** binary when available (weights already inside).
- Remotes need `myco` on the **remote** PATH used by non-interactive SSH (`BatchMode`);
`~/.local/bin` or `~/.cargo/bin` are common — verify with
`ssh -o BatchMode=yes <alias> 'command -v myco; myco --version'`.
- After replacing binaries, the **interactive CLI must be restarted** to load a new agent binary;
remote **host** workers respawn on next tool use (or after `/hosts` shows DOWN and reconnect).
- Ask before destructive remote installs; prefer installing into user prefixes (`~/.local`,
`~/.cargo`) over system paths.
## Diagnosis checklist
When tools fail or the user asks why something is broken, investigate with tools:
1. **Host down / unavailable**
- **Local** never needs a host subprocess; if local tools fail, debug the agent process itself.
- Read `~/.ssh/config` for `Host` aliases (remote names == destinations);
`~/.myco/config.toml` (or `$MYCO_CONFIG`) only for knobs.
- On remote: `ssh -o BatchMode=yes <alias> 'which myco; myco --help'` via the
**local** host's bash. If missing/outdated: install a **binary built for that
platform** (release asset — weights already embedded), or **build on that host**
from source. Do not copy binaries across mismatched OS/arch/glibc.
- Confirm SSH alias works: `ssh -o BatchMode=yes <alias> true`.
- If auth fails with BatchMode: check `ssh-add -l` and the startup ssh-agent
preflight (silent when clean; problems open a WARNING block before the first
USER block).
Unlock with `ssh-add` / `ssh-add --apple-use-keychain <key>` (myco cannot prompt on the
NDJSON pipe). Restart myco after loading keys.
- Suggest user run `/hosts` after fixes (requires CLI restart to re-attach remotes).
2. **Wrong machine / wrong files**
- Check whether `host` was set; default is always `local`.
- `bash` `uname -n` / `pwd` / `hostname` on the intended `host`.
3. **Session / state confusion**
- Conversation resume ≠ restored bash sessions or editor state.
- Bash sessions die when the host process exits (CLI exit, host crash, SSH drop). Local
in-process sessions die with the agent process.
4. **Explain product limits honestly**
- No heartbeat in V1: remote liveness is next tool error; local is always in-process.
- No mid-flight cancel over the host pipe yet; Ctrl-C cancels the agent turn locally.
- You cannot invoke slash-commands; tell the user which to run.
When helping the user change config, prefer **surgical edits** to `~/.ssh/config` (hosts) or
`~/.myco/config.toml` (knobs) and show a minimal diff. Ask before destructive remote installs.