Skip to content

v0.40.0 — your pit, on every machine

Choose a tag to compare

@ralyodio ralyodio released this 11 Aug 09:26
c8778ed

Your pit stops being one machine's pit.

/save and /load — your settings, on your account

A pit becomes yours by accretion: a dozen aliases, herd rules you tuned until the roster stopped lying to you. All of it lived in ~/.moshcode on exactly one machine, so every new laptop, container and droplet started as a stranger.

/save                  # push this machine's settings to app.moshcode.sh
/save --dry-run         # what would go up, and stop

# on the new box
/login
/load                  # bring them down
/load --dry-run         # the per-file plan, changing nothing

Also moshcode save and moshcode load, both with --json so a provisioning script can act on the result.

What syncs is an allowlist, not a directory walk

~/.moshcode/aliases.json and ~/.moshcode/herd/rules.json.

Never: credentials.json — the account token this very feature authenticates with — plus live herd state, the package cache, and your history. A walk that gains a file gains it silently; an allowlist has to be edited on purpose, in a diff someone reviews, and a second list names the never-synced files so a future addition cannot quietly leak the token.

Engine configuration (~/.claude.json and friends) is deliberately left alone. Those files carry provider API keys, and /load has to stay safe to run on a machine you share.

The allowlist is checked again on the way in. A snapshot is data from the network, and a name in it is a path this process would write — without that second check, a bad snapshot spelling ../../.ssh/authorized_keys would make /load a remote write primitive.

Nothing is overwritten quietly

Each save is a numbered revision, and /save sends the revision it last agreed on. If another machine saved in the meantime the write is refused and you are told, with /load and /save --force as the two ways out — rather than one machine silently erasing the other. The compare-and-set lives inside the insert, because two saves in flight against a network database otherwise both read the same revision number and one of them vanishes.

/load refuses to replace a settings file you edited since this machine last synced, and names the file. --force overrides it; --dry-run shows you the difference first.

An unchanged /save costs no history: the account recognises a byte-identical snapshot and answers with the revision it already holds. That answer comes from the account rather than from a local marker, so a machine whose settings were deleted from the web finds out instead of insisting it is already up to date.

Seeing it from the web

The last ten revisions are at app.moshcode.sh/settings/sync, each with the machine and moshcode version it came from. Promote an older one to current, or delete the lot — your machines are untouched either way, that only empties the account copy. The page lists file names and never their contents.

The DNS bridge is proved before your machine is routed at it

moshcode dns enable used to print bridge started (pid …) in the same tick it spawned the daemon — before the child had done anything, including exist. On a machine where the daemon dies on startup that confident line was followed by catch-all routing (Domains=~.) pointing every lookup on the box at a dead port: no DNS at all, and no way to find out why, because the daemon had written the reason to a stderr that went to /dev/null.

Now the daemon's output lands in moshpit-dns.log next to the pidfile, an early exit is reported as a failed start carrying that output, and no pidfile is left behind for a process that is gone — which is what used to make the next run believe a bridge was already up.

Found on a Kubuntu desktop whose node comes from mise. The specific cause matters less than the class: every startup failure used to arrive as the same success line.

Install

curl -fsSL https://raw.githubusercontent.com/moshcoder/moshcode/main/install.sh | bash

or npm i -g moshcode@0.40.0