moshcode 0.60.0 → 0.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -601,12 +601,57 @@ moshcode install doctl # GitHub release binary → ~/.local/bin
601
601
  moshcode install turso # official script → ~/.turso (new shell to pick up PATH)
602
602
  moshcode install tailscale # official script; system daemon, so it needs root
603
603
  moshcode install coral # official script → ~/.local/bin (checksum-verified)
604
+ moshcode install spinifex # official script; Linux host platform, so it needs root
604
605
 
605
606
  moshcode gh pr list # straight through to the native CLI
606
607
  moshcode railway up
607
608
  moshcode doctl compute droplet list
609
+ moshcode spinifex ec2 describe-instances
608
610
  ```
609
611
 
612
+ ### Spinifex — your own AWS-compatible cloud
613
+
614
+ [Spinifex](https://mulgadc.com/spinifex) is the other end of the infra list:
615
+ instead of driving someone else's cloud, it turns your own hardware into one.
616
+ EC2, EBS, S3, VPC, and IAM, API-compatible with AWS, on bare metal, edge boxes,
617
+ or on-prem racks — so the same `aws` calls and Terraform providers work against
618
+ hardware you own.
619
+
620
+ ```sh
621
+ moshcode install spinifex # curl -fsSL https://install.mulgadc.com | bash
622
+ moshcode spinifex version # straight through to the native `spx` CLI
623
+ moshcode spinifex admin init --node node1 --nodes 1
624
+ ```
625
+
626
+ The product is Spinifex, the binary is `spx`, and `moshcode spinifex …` is exact
627
+ passthrough to it — the same split as `moshcode secrets` and `logicsrc`.
628
+
629
+ Spinifex is a host platform, not a standalone binary, so its installer is the
630
+ most invasive one on this list. Read this before running it:
631
+
632
+ - **Linux only**, and specifically Ubuntu 26.04 or Debian 13. The installer
633
+ pulls QEMU/KVM, OVN/Open vSwitch, and the AWS CLI through apt.
634
+ - **Root.** It writes `/usr/local/bin/spx`, systemd units, and scoped
635
+ `sudoers.d` rules. Like tailscale, it finds sudo itself; MoshCode only gets
636
+ the password prompt out of the way first.
637
+ - **Your WAN interface must already be bridged to `br-wan`** before you start —
638
+ check with `ip -br link show br-wan`. The installer does not create it, and
639
+ bridging a live uplink can drop the box off the network.
640
+
641
+ After it finishes, Spinifex's own docs take over — `setup-ovn.sh --management`,
642
+ `spx admin init`, then `systemctl start spinifex.target`. See
643
+ [docs.mulgadc.com/docs/install](https://docs.mulgadc.com/docs/install).
644
+
645
+ MoshCode passes `INSTALL_SPINIFEX_SKIP_NEWGRP=1`, because on a TTY the vendor
646
+ script ends by `exec`ing `newgrp spinifex` to activate the new group. That would
647
+ strand you in a subshell instead of returning to the pit — and would park the
648
+ rest of a `moshcode update` run behind it. Log in again (or run `newgrp
649
+ spinifex` yourself) to pick up the group.
650
+
651
+ Re-running `moshcode install spinifex` is also its upgrade path: the installer
652
+ detects the existing install, replaces the binary, applies pending config
653
+ migrations, and restarts the services.
654
+
610
655
  ### MCP server testing
611
656
 
612
657
  ```sh
@@ -625,9 +670,10 @@ MoshCode resolves the latest GitHub release and drops the binary in
625
670
  `$MOSHCODE_BIN` (default `~/.local/bin`) — no sudo, no package manager. Set
626
671
  `MOSHCODE_BIN` to install elsewhere.
627
672
 
628
- `tailscale` is the exception: it is a system daemon, so its official installer
629
- goes through your distro's package manager and will ask for sudo (on macOS it
630
- delegates to the App Store).
673
+ `tailscale` and `spinifex` are the exceptions: both install system services
674
+ rather than a user-local binary, so their official installers go through the
675
+ distro's package manager and will ask for sudo (tailscale on macOS delegates to
676
+ the App Store instead; Spinifex has no macOS build at all).
631
677
 
632
678
  MoshCode asks for that password **before** starting the work rather than letting
633
679
  the installer stop for it partway through — which matters most in `moshcode
@@ -1283,6 +1329,7 @@ chmod +x deploy.mosh
1283
1329
  | `coral(args…)` | drive the Coral CLI (SQL over APIs, databases, internal systems) |
1284
1330
  | `alpaca(args…)` | drive the native Alpaca trading CLI |
1285
1331
  | `mcpjam(args…)` | drive the MCPJam CLI (test, debug, and validate MCP servers) |
1332
+ | `spinifex(args…)` | drive the Spinifex CLI (`spx` — AWS-compatible cloud on your own hardware) |
1286
1333
  | `trade(args…)` | look up tickers, inspect markets, preview/place Alpaca orders |
1287
1334
  | `stocks(args…)` | research tickers via advis0r (`stocksRead` returns the data) |
1288
1335
  | `crypto(args…)` | research crypto pairs via advis0r (`cryptoRead` returns the data) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moshcode",
3
- "version": "0.60.0",
3
+ "version": "0.61.0",
4
4
  "type": "module",
5
5
  "description": "moshcode — a metal wrapper for coding engines and native UGig/CoinPay workflow CLIs, with OpenPRD and moshscript",
6
6
  "repository": {
package/src/commands.mjs CHANGED
@@ -680,6 +680,7 @@ const COMMANDS = [
680
680
  cliVerb("coral", "drive the Coral CLI (SQL over APIs, databases, and internal systems)"),
681
681
  cliVerb("alpaca", "drive the native Alpaca trading CLI"),
682
682
  cliVerb("mcpjam", "drive the MCPJam CLI (test, debug, and validate MCP servers)"),
683
+ cliVerb("spinifex", "drive the Spinifex CLI (spx — AWS-compatible cloud on your own hardware)"),
683
684
  cliVerb("trade", "look up tickers, inspect markets, and preview/place Alpaca orders"),
684
685
  cliVerb("pwd", "print the current repo/location"),
685
686
 
package/src/tools.mjs CHANGED
@@ -212,6 +212,37 @@ export const TOOLS = {
212
212
  // idempotent, so it doubles as the upgrade path — no `upgrade` key needed.
213
213
  install: { cmd: "npm", args: ["install", "-g", "@mcpjam/cli"] },
214
214
  },
215
+ spinifex: {
216
+ desc: "Spinifex — AWS-compatible cloud on your own hardware (EC2, EBS, S3, VPC, IAM)",
217
+ // The product is Spinifex; the binary it installs is `spx`. Same split as
218
+ // `secrets` → `logicsrc`: the moshcode command reads as the product name.
219
+ bin: "spx",
220
+ // https://docs.mulgadc.com/docs/install — the vendor script drops
221
+ // /usr/local/bin/spx, installs systemd units and scoped sudoers rules, and
222
+ // pulls QEMU/OVN/AWS CLI through apt, so it is Linux-only (Ubuntu 26.04 /
223
+ // Debian 13) and always escalates. It finds sudo itself, like tailscale's,
224
+ // so needsRoot only says a password prompt is coming — see primeEscalation.
225
+ //
226
+ // The script is bash (it uses bashisms and documents `| bash`), so `sh -c
227
+ // "curl … | sh"` would not do.
228
+ //
229
+ // INSTALL_SPINIFEX_SKIP_NEWGRP is the important part: on a TTY the
230
+ // installer finishes with `exec newgrp spinifex`, replacing itself with an
231
+ // interactive subshell to activate the new group. Under `moshcode install`
232
+ // that never returns — the operator lands in a subshell instead of back in
233
+ // the pit, and inside `moshcode update` it would park the rest of the plan
234
+ // behind a shell nobody asked for. Skipping it costs nothing a new login
235
+ // shell does not fix.
236
+ needsRoot: true,
237
+ install: {
238
+ cmd: "bash",
239
+ args: ["-c", "curl -fsSL https://install.mulgadc.com | INSTALL_SPINIFEX_SKIP_NEWGRP=1 bash"],
240
+ },
241
+ // Re-running the installer is Spinifex's own documented update path — it
242
+ // detects the existing install, replaces the binary, runs pending config
243
+ // migrations, and restarts the services. toolUpgradeSpec falls back to
244
+ // install, so there is deliberately no upgrade key.
245
+ },
215
246
  };
216
247
 
217
248
  /** Resolve a name to `[key, tool]`, or null. */