docs: STATUS.md — FUSE/SSHFS development loop section
Dedicated section covering the file-ops-via-mount + git/cargo-via-ssh split that makes this dev setup work. Includes: - Exact running mount command (pulled from ps) - macFUSE + sshfs-mac brew install path - Health check + recovery sequence for when mount hangs (it will) - Full which-path-for-which-operation table - Don't-do list (cargo from mount, rsync without AppleDouble exclude, etc) - Cache caveat and inode-sharing note between mount and SSH views No code change.
This commit is contained in:
parent
bb2e3fab42
commit
cad63bdd76
@ -12,13 +12,96 @@ Updated: 2026-04-23 (Dashboard Stop UX bug diagnosed; async-spawn fix fully desi
|
||||
|
||||
### How to work on this repo (SSH + SSHFS setup)
|
||||
|
||||
You are likely running on the **laptop** (macOS). The repo lives on the **ThinkPad** (.116). There are two access paths, use both:
|
||||
You are likely running on the **laptop** (macOS). The repo lives on the **ThinkPad** (.116). There are two access paths, use both in parallel:
|
||||
|
||||
1. **SSHFS mount at `~/mnt/archy-thinkpad/`** — use for `read` / `edit` / `write` / `glob` / `grep` tools. Fast for file ops, too slow for git/cargo. Example: `/Users/dorian/mnt/archy-thinkpad/core/archipelago/src/api/rpc/container.rs`.
|
||||
- Mount source: `archy:Projects/archy` (via the `archy` SSH alias, so it uses `~/.ssh/archy_opencode`)
|
||||
- If mount is missing/stale, remount: `sshfs archy:Projects/archy ~/mnt/archy-thinkpad -o reconnect,ServerAliveInterval=15`
|
||||
- AppleDouble `._*` files leak from macOS writes — add `--exclude="._*"` to any `rsync` over the mount; single-file `edit`/`write` is fine.
|
||||
2. **SSH directly** — use for `git`, `cargo`, `npm`, running the server. SSH config aliases are already set up in `~/.ssh/config`:
|
||||
1. **SSHFS mount at `~/mnt/archy-thinkpad/`** — for all file ops (`read`/`edit`/`write`/`glob`/`grep`).
|
||||
2. **Direct SSH** — for everything that isn't file ops: `git`, `cargo`, `npm`, `systemctl`, running the server, tailing logs.
|
||||
|
||||
See the "FUSE / SSHFS development loop" section below for the full mount lifecycle — that's _the_ thing that makes this dev setup work, and it will break periodically.
|
||||
|
||||
### FUSE / SSHFS development loop
|
||||
|
||||
**Why this exists**: editing the repo directly on the ThinkPad over raw SSH means no IDE, no tool-native file reads, no glob/grep speed. SSHFS mounts the remote filesystem as a local directory so OpenCode's file tools work transparently. But SSHFS is a leaky abstraction — know the gotchas or you'll waste hours.
|
||||
|
||||
**Stack** (macOS laptop):
|
||||
- **macFUSE** — kernel extension providing FUSE on macOS. Install via `brew install --cask macfuse` (requires reboot + security approval in System Settings the first time).
|
||||
- **sshfs** — userspace mount tool. Install via `brew install gromgit/fuse/sshfs-mac` (the homebrew core `sshfs` was removed; use this tap).
|
||||
- Verify: `which sshfs` → `/opt/homebrew/bin/sshfs`, `sshfs --version` → `SSHFS version 2.10 / FUSE library version 2.9.9`.
|
||||
|
||||
**Actual mount command currently running** (verified from `ps`):
|
||||
```
|
||||
sshfs archy:Projects/archy /Users/dorian/mnt/archy-thinkpad \
|
||||
-o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,volname=archy-thinkpad
|
||||
```
|
||||
|
||||
Breakdown:
|
||||
- `archy:Projects/archy` — remote path via the `archy` SSH alias (uses `~/.ssh/archy_opencode`, no password prompt).
|
||||
- `~/mnt/archy-thinkpad` — local mount point. Create once: `mkdir -p ~/mnt/archy-thinkpad`.
|
||||
- `reconnect` — sshfs auto-reconnects if the TCP session drops (WiFi flap, laptop sleep). Without this, the mount turns into a zombie immediately.
|
||||
- `ServerAliveInterval=15` — sends a keepalive every 15s.
|
||||
- `ServerAliveCountMax=3` — disconnect after 3 missed keepalives (45s). Tune up if your network is flaky.
|
||||
- `volname=archy-thinkpad` — Finder display name.
|
||||
|
||||
**Check mount health**:
|
||||
```
|
||||
mount | grep archy-thinkpad
|
||||
# should print: archy:Projects/archy on /Users/dorian/mnt/archy-thinkpad (macfuse, nodev, nosuid, synchronous, mounted by dorian)
|
||||
|
||||
ls ~/mnt/archy-thinkpad/ | head
|
||||
# should list repo contents fast (<1s). If it hangs, mount is stale.
|
||||
```
|
||||
|
||||
**Recovery when the mount hangs / goes stale** (this WILL happen — laptop sleeps, WiFi drops, ThinkPad reboots):
|
||||
```
|
||||
# 1. Force-unmount (macOS — `umount` alone often fails on a hung FUSE mount)
|
||||
sudo diskutil unmount force ~/mnt/archy-thinkpad
|
||||
# fallback if diskutil can't see it:
|
||||
sudo umount -f ~/mnt/archy-thinkpad
|
||||
|
||||
# 2. Kill any zombie sshfs process
|
||||
pkill -f "sshfs archy:Projects/archy"
|
||||
|
||||
# 3. Remount
|
||||
sshfs archy:Projects/archy ~/mnt/archy-thinkpad \
|
||||
-o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,volname=archy-thinkpad
|
||||
|
||||
# 4. Verify
|
||||
ls ~/mnt/archy-thinkpad/ | head
|
||||
```
|
||||
|
||||
If the mount point itself got wedged (`ls: /Users/dorian/mnt/archy-thinkpad: Device not configured`), the sequence above still works — macFUSE garbage-collects the inode after the force-unmount.
|
||||
|
||||
**When to use which path** (rules, not suggestions):
|
||||
| Operation | Use | Why |
|
||||
|---|---|---|
|
||||
| `read` / `edit` / `write` | SSHFS mount | OpenCode tools want local paths |
|
||||
| `glob` / `grep` | SSHFS mount | Local FS traversal is fine; remote would need rg over SSH |
|
||||
| Reading many files | SSHFS mount | Each read is a round-trip but parallelizable |
|
||||
| `git status` / `git diff` / `git log` | SSH | Git over FUSE is painfully slow (lots of stat calls) |
|
||||
| `git add` / `git commit` | SSH | Same — commit times grow linearly with tree size on FUSE |
|
||||
| `cargo check` / `cargo test` / `cargo build` | SSH | Compiling over FUSE would take hours; cargo's incremental stat pattern destroys FUSE performance |
|
||||
| `npm install` / `npm run build` | SSH | Same reason — massive file churn |
|
||||
| Running the server / tailing journal | SSH | Service lives on .116 |
|
||||
| Deploying to .228 | SSH from .116 | SCP from ThinkPad; laptop isn't in the critical path |
|
||||
|
||||
**Don't do this** (will bite you):
|
||||
- `cargo build` from the mount — will try to write target/ over FUSE, gets orders of magnitude slower, may hang.
|
||||
- `rsync` without `--exclude="._*"` — macOS writes AppleDouble metadata files, they leak to the remote as `._*` siblings of every real file. `.gitignore` already excludes them (commit `13858842`), but they clutter the tree.
|
||||
- Writing big binary files via the mount — use `scp` over SSH instead.
|
||||
- Relying on file-change-watcher tools (watchman, chokidar) — they get confused by FUSE event semantics.
|
||||
|
||||
**Editing workflow in a typical session**:
|
||||
1. Laptop: OpenCode `read`s a file via `/Users/dorian/mnt/archy-thinkpad/...`. FUSE fetches it over SSH, caches briefly.
|
||||
2. Laptop: OpenCode `edit`s the file — FUSE writes the new bytes back to .116 immediately (synchronous mount).
|
||||
3. Laptop: `ssh archy "cd ~/Projects/archy && ~/.cargo/bin/cargo check -p archipelago"` — runs on the real filesystem on .116, sees the edit.
|
||||
4. Laptop: `ssh archy "cd ~/Projects/archy && git diff path/to/file"` — confirms the edit landed.
|
||||
5. Laptop: `ssh archy "cd ~/Projects/archy && git add path/to/file && git commit -m '...'"` — commit from .116.
|
||||
|
||||
The SSHFS mount and the SSH shell are pointing at **the same inodes** — edits via the mount are instantly visible to `cargo`/`git` over SSH. There's no "sync" step.
|
||||
|
||||
**Cache caveat**: macFUSE caches attributes briefly (default ~1s). If you write via SSH and read via the mount within that window, you may see stale metadata. The mount's `synchronous` flag (visible in `mount` output) minimizes but doesn't eliminate this. If you get a weird diff between what SSH and the mount report, re-read after a second, or `stat --file-system ~/mnt/archy-thinkpad/<file>` to force a refresh.
|
||||
|
||||
**Direct SSH** access (use when FUSE isn't the right tool):
|
||||
- `ssh archy` → `archipelago@192.168.1.116` using `~/.ssh/archy_opencode`
|
||||
- `ssh archy228` → `archipelago@192.168.1.228` using `~/.ssh/archy_opencode`
|
||||
- Full host form also works: `ssh archipelago@192.168.1.116` / `ssh archipelago@192.168.1.228` (same key resolves via IdentitiesOnly).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user