moshcode 0.24.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/LICENSE +21 -0
- package/README.md +580 -0
- package/bin/moshcode.mjs +674 -0
- package/bin/moshscript.mjs +29 -0
- package/examples/alive.mosh +6 -0
- package/examples/scripting-the-cli.mosh +21 -0
- package/examples/team-secrets.mosh +20 -0
- package/examples/templates/bun-caddy-sqlite/.env.example +14 -0
- package/examples/templates/bun-caddy-sqlite/Caddyfile +18 -0
- package/examples/templates/bun-caddy-sqlite/README.md +97 -0
- package/examples/templates/bun-caddy-sqlite/deploy/moshcode-dns.service +39 -0
- package/examples/templates/bun-caddy-sqlite/deploy/moshpit-service.service +38 -0
- package/examples/templates/bun-caddy-sqlite/package.json +15 -0
- package/examples/templates/bun-caddy-sqlite/src/db.ts +47 -0
- package/examples/templates/bun-caddy-sqlite/src/server.ts +44 -0
- package/examples/templates/bun-caddy-sqlite/template.json +10 -0
- package/examples/templates/caddy-proxy/Caddyfile +36 -0
- package/examples/templates/caddy-proxy/README.md +104 -0
- package/examples/templates/caddy-proxy/deploy/moshcode-dns.service +39 -0
- package/examples/templates/caddy-proxy/template.json +8 -0
- package/examples/templates/caddy-static/Caddyfile +16 -0
- package/examples/templates/caddy-static/README.md +90 -0
- package/examples/templates/caddy-static/deploy/moshcode-dns.service +39 -0
- package/examples/templates/caddy-static/site/index.html +11 -0
- package/examples/templates/caddy-static/template.json +8 -0
- package/install.sh +194 -0
- package/package.json +28 -0
- package/prd/0000-template.md +49 -0
- package/prd/0001-wrap-ugig-and-coinpay-clis.md +121 -0
- package/prd/0002-separate-agent-and-raw-engine-launches.md +113 -0
- package/prd/0003-cross-engine-mcp-and-skill-installation.md +165 -0
- package/prd/0004-moshscript-run-programmable-moshcode.md +344 -0
- package/prd/0005-hosted-moshpit-resolver.md +192 -0
- package/prd/0006-help.md +359 -0
- package/prd/0007-profullstack-site-init.md +1183 -0
- package/prd/README.md +26 -0
- package/src/ads.mjs +58 -0
- package/src/auth.mjs +193 -0
- package/src/cli-schema.mjs +533 -0
- package/src/cli.mjs +118 -0
- package/src/commands.mjs +259 -0
- package/src/completion.mjs +594 -0
- package/src/console.mjs +244 -0
- package/src/dns-system.mjs +404 -0
- package/src/dns.mjs +2872 -0
- package/src/doh-server.mjs +256 -0
- package/src/doh.mjs +218 -0
- package/src/engines.mjs +385 -0
- package/src/escalate.mjs +85 -0
- package/src/help.mjs +443 -0
- package/src/integrations.mjs +265 -0
- package/src/mcp-catalog.mjs +50 -0
- package/src/mcp.mjs +155 -0
- package/src/mirror.mjs +187 -0
- package/src/notify.mjs +86 -0
- package/src/open-url.mjs +34 -0
- package/src/parking-http.mjs +65 -0
- package/src/pins.mjs +190 -0
- package/src/pit-url.mjs +13 -0
- package/src/prd.mjs +341 -0
- package/src/pty.mjs +176 -0
- package/src/pwd.mjs +103 -0
- package/src/registry.mjs +37 -0
- package/src/release-install.mjs +191 -0
- package/src/runtime.mjs +161 -0
- package/src/selfupdate.mjs +215 -0
- package/src/serve.mjs +502 -0
- package/src/skills.mjs +93 -0
- package/src/tabs.mjs +144 -0
- package/src/templates.mjs +456 -0
- package/src/tools.mjs +231 -0
- package/src/trade.mjs +137 -0
- package/src/trust.mjs +712 -0
- package/src/tui.mjs +736 -0
- package/src/ui.mjs +49 -0
- package/src/uninstall.mjs +113 -0
- package/src/upgrade.mjs +217 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# caddy-static
|
|
2
|
+
|
|
3
|
+
A static site at a Moshpit name. No runtime, no database, no service to keep
|
|
4
|
+
alive — Caddy and a directory of files.
|
|
5
|
+
|
|
6
|
+
Reach for [`bun-caddy-sqlite`](../bun-caddy-sqlite) instead when you need
|
|
7
|
+
something that runs.
|
|
8
|
+
|
|
9
|
+
## The part that surprises people
|
|
10
|
+
|
|
11
|
+
Three machines' worth of concerns, and they fail independently:
|
|
12
|
+
|
|
13
|
+
| | needs the resolver? | what it does |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| the box serving the name | **no** | Caddy matches a `Host` header, nothing more |
|
|
16
|
+
| the registry | — | holds the address the name points at |
|
|
17
|
+
| every visitor | **yes** | `sudo moshcode dns enable`, or the name resolves to nothing |
|
|
18
|
+
|
|
19
|
+
Nothing on the server ever resolves its own name. That is why there is no DNS
|
|
20
|
+
software in this template.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
1. **Point the name at the box.** In the Pit, set `points at` to its public
|
|
25
|
+
IPv6 address — bare, no scheme, no brackets, no port:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
ip -6 addr show scope global | grep inet6
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Pick the globally routable one. An `fd..`/`fc..` address is unique-local
|
|
32
|
+
(Tailscale and friends live there) and the registry refuses it, because a
|
|
33
|
+
name pointed at one resolves somewhere only you can reach.
|
|
34
|
+
|
|
35
|
+
2. **Put the files where the Caddyfile expects them.** `SITE_ROOT` defaults to
|
|
36
|
+
`/srv/moshpit-site`; `site/` here is a placeholder to replace.
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
sudo mkdir -p /srv/moshpit-site
|
|
40
|
+
sudo cp -r site/. /srv/moshpit-site/
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. **Serve it.**
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
export MOSHPIT_NAME=foo.whatever
|
|
47
|
+
export SITE_ROOT=/srv/moshpit-site
|
|
48
|
+
sudo cp Caddyfile /etc/caddy/Caddyfile
|
|
49
|
+
sudo systemctl enable --now caddy
|
|
50
|
+
sudo ufw allow 80/tcp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
4. **Reach it,** on any machine that should see the name:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
sudo moshcode dns enable
|
|
57
|
+
sudo cp deploy/moshcode-dns.service /etc/systemd/system/ # survives reboot
|
|
58
|
+
sudo systemctl enable --now moshcode-dns
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Verifying, one layer at a time
|
|
62
|
+
|
|
63
|
+
A failure at any layer looks identical in a browser, so do not start there.
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
# Server only — no DNS involved. Proves Caddy and the firewall.
|
|
67
|
+
curl -6 -H "Host: foo.whatever" http://[YOUR:V6:ADDR]/
|
|
68
|
+
|
|
69
|
+
# Resolver only. Proves the registry and the bridge.
|
|
70
|
+
moshcode dns resolve foo.whatever
|
|
71
|
+
|
|
72
|
+
# Both.
|
|
73
|
+
curl -6 http://foo.whatever/
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If the first works and the last does not, it is DNS. If the first fails, stop
|
|
77
|
+
looking at DNS.
|
|
78
|
+
|
|
79
|
+
## Known limits
|
|
80
|
+
|
|
81
|
+
- **No HTTPS, ever.** No CA will issue for an ending outside the DNS root. That
|
|
82
|
+
rules out secure cookies, service workers, and WebCrypto in the browser. The
|
|
83
|
+
`http://` in the Caddyfile is what stops Caddy trying and failing.
|
|
84
|
+
- **Only machines running the resolver can reach the name.** Not phones, not a
|
|
85
|
+
colleague who has not installed it, not webhooks.
|
|
86
|
+
`pit.moshcode.sh/n/foo.whatever` is the URL for people who installed nothing.
|
|
87
|
+
- **One level deep.** `foo.whatever` works; `www.foo.whatever` does not.
|
|
88
|
+
- **Port 80 only** on the resolver path. A DNS record carries an address and has
|
|
89
|
+
nowhere to put a port, so a target like `[addr]:8080` only works through the
|
|
90
|
+
`/n/` gateway.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# The Moshpit resolver, kept running across reboots.
|
|
2
|
+
#
|
|
3
|
+
# `moshcode dns enable` sets up two halves: a systemd-resolved drop-in that
|
|
4
|
+
# routes Moshpit endings at the bridge, and the bridge process itself. The
|
|
5
|
+
# drop-in is a file and survives a reboot on its own. The process does not —
|
|
6
|
+
# so after a restart the routing still points at a port with nothing behind it,
|
|
7
|
+
# and every Moshpit name stops resolving with no obvious cause. This unit is
|
|
8
|
+
# the missing half.
|
|
9
|
+
#
|
|
10
|
+
# sudo cp deploy/moshcode-dns.service /etc/systemd/system/
|
|
11
|
+
# sudo systemctl enable --now moshcode-dns
|
|
12
|
+
#
|
|
13
|
+
# Install this on machines that need to REACH Moshpit names. A box that only
|
|
14
|
+
# serves one does not need it — Caddy answers whatever Host header arrives and
|
|
15
|
+
# never resolves its own name.
|
|
16
|
+
|
|
17
|
+
[Unit]
|
|
18
|
+
Description=Moshpit DNS bridge
|
|
19
|
+
After=network-online.target
|
|
20
|
+
Wants=network-online.target
|
|
21
|
+
Before=systemd-resolved.service
|
|
22
|
+
|
|
23
|
+
[Service]
|
|
24
|
+
Type=simple
|
|
25
|
+
# Port 5354 is unprivileged, so this does not need root. The trade-off is that
|
|
26
|
+
# the parking responder cannot take port 80 and falls back to the public
|
|
27
|
+
# parking address — which only affects names that point nowhere yet.
|
|
28
|
+
ExecStart=/usr/bin/env moshcode dns start --port 5354
|
|
29
|
+
Restart=always
|
|
30
|
+
RestartSec=2
|
|
31
|
+
|
|
32
|
+
DynamicUser=yes
|
|
33
|
+
NoNewPrivileges=yes
|
|
34
|
+
PrivateTmp=yes
|
|
35
|
+
ProtectSystem=strict
|
|
36
|
+
ProtectHome=yes
|
|
37
|
+
|
|
38
|
+
[Install]
|
|
39
|
+
WantedBy=multi-user.target
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<meta charset="utf-8">
|
|
3
|
+
<title>served at a moshpit name</title>
|
|
4
|
+
<h1>It resolved.</h1>
|
|
5
|
+
<p>
|
|
6
|
+
Your resolver answered this name out of the Moshpit registry and connected
|
|
7
|
+
straight to the box holding it. Nothing proxied, nothing redirected.
|
|
8
|
+
</p>
|
|
9
|
+
<p>
|
|
10
|
+
Replace this file. It lives in whatever <code>SITE_ROOT</code> points at.
|
|
11
|
+
</p>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "caddy-static",
|
|
3
|
+
"description": "Caddy serving a static site at a Moshpit name — no runtime, no service to keep alive",
|
|
4
|
+
"vars": {
|
|
5
|
+
"MOSHPIT_NAME": "the registered name to serve, e.g. foo.whatever",
|
|
6
|
+
"SITE_ROOT": "directory of files to serve (default /srv/moshpit-site)"
|
|
7
|
+
}
|
|
8
|
+
}
|
package/install.sh
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# moshcode — one-line installer 🤘
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# curl -fsSL https://moshcoding.com/install.sh | sh
|
|
6
|
+
# curl -fsSL https://moshcoding.com/install.sh | sh -s -- update (alias: upgrade)
|
|
7
|
+
# curl -fsSL https://moshcoding.com/install.sh | sh -s -- remove (alias: uninstall)
|
|
8
|
+
#
|
|
9
|
+
# (also works straight from GitHub:)
|
|
10
|
+
# curl -fsSL https://raw.githubusercontent.com/moshcoder/moshcode/main/install.sh | sh
|
|
11
|
+
#
|
|
12
|
+
# What it does — dead simple, no build step:
|
|
13
|
+
# 1. Checks for Node.js 18+ (moshcode is zero-dependency ESM — needs a node).
|
|
14
|
+
# 2. Downloads the latest release tarball of moshcoder/moshcode from GitHub
|
|
15
|
+
# (falls back to the main branch if no release is published yet).
|
|
16
|
+
# 3. Unpacks it to $MOSHCODE_HOME (default: $HOME/.moshcode).
|
|
17
|
+
# 4. Drops a `moshcode` wrapper at $MOSHCODE_BIN (default: $HOME/.local/bin)
|
|
18
|
+
# that just exec's `node $MOSHCODE_HOME/bin/moshcode.mjs "$@"`.
|
|
19
|
+
# 5. Ensures that bin dir is on your PATH.
|
|
20
|
+
#
|
|
21
|
+
# Env overrides:
|
|
22
|
+
# MOSHCODE_HOME=/path install dir (default: $HOME/.moshcode)
|
|
23
|
+
# MOSHCODE_BIN=/path/dir wrapper bin dir (default: $HOME/.local/bin)
|
|
24
|
+
# MOSHCODE_REF=vX.Y.Z pin a tag/branch (default: latest release, else main)
|
|
25
|
+
# MOSHCODE_ALLOW_ROOT=1 install as root anyway (see below)
|
|
26
|
+
#
|
|
27
|
+
# Do not install this with sudo. moshcode is a user-level CLI, and every path
|
|
28
|
+
# here is derived from $HOME — under sudo that is /root, so the payload and the
|
|
29
|
+
# wrapper land in root's home where your own user cannot read them. Nothing
|
|
30
|
+
# fails at install time; it surfaces later as "permission denied" on a binary
|
|
31
|
+
# that looks installed. The installer refuses that case and tells you how.
|
|
32
|
+
#
|
|
33
|
+
# Re-running updates an existing install in place.
|
|
34
|
+
|
|
35
|
+
set -eu
|
|
36
|
+
|
|
37
|
+
REPO="moshcoder/moshcode"
|
|
38
|
+
INSTALL_URL="https://moshcoding.com/install.sh"
|
|
39
|
+
MOSHCODE_HOME="${MOSHCODE_HOME:-$HOME/.moshcode}"
|
|
40
|
+
MOSHCODE_BIN="${MOSHCODE_BIN:-$HOME/.local/bin}"
|
|
41
|
+
WRAPPER="$MOSHCODE_BIN/moshcode"
|
|
42
|
+
SCRIPT_WRAPPER="$MOSHCODE_BIN/moshscript"
|
|
43
|
+
|
|
44
|
+
# ---- pretty output (acid-lime, matching the CLI) --------------------------
|
|
45
|
+
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
|
|
46
|
+
ACID=$(printf '\033[38;2;158;240;26m'); ASH=$(printf '\033[38;2;139;147;138m')
|
|
47
|
+
RED=$(printf '\033[31m'); BOLD=$(printf '\033[1m'); RESET=$(printf '\033[0m')
|
|
48
|
+
else
|
|
49
|
+
ACID=''; ASH=''; RED=''; BOLD=''; RESET=''
|
|
50
|
+
fi
|
|
51
|
+
info() { printf '%s·%s %s\n' "$ASH" "$RESET" "$*"; }
|
|
52
|
+
ok() { printf '%s✓%s %s\n' "$ACID" "$RESET" "$*"; }
|
|
53
|
+
fail() { printf '%s✗%s %s\n' "$RED" "$RESET" "$*" >&2; exit 1; }
|
|
54
|
+
|
|
55
|
+
# ---- prerequisites --------------------------------------------------------
|
|
56
|
+
need() { command -v "$1" >/dev/null 2>&1 || fail "$1 is required but not found."; }
|
|
57
|
+
|
|
58
|
+
# Installing under sudo silently installs for the wrong user. Every path here
|
|
59
|
+
# comes from $HOME, which sudo sets to /root, so the payload and wrappers land
|
|
60
|
+
# in a directory mode 0700 root — invisible to the user who ran the command.
|
|
61
|
+
# The install reports success and only breaks later, at first use.
|
|
62
|
+
#
|
|
63
|
+
# A bare root shell (containers, CI images, root-only boxes) has no SUDO_USER
|
|
64
|
+
# and is a legitimate way to install, so only the sudo-from-a-real-user case is
|
|
65
|
+
# refused, and MOSHCODE_ALLOW_ROOT overrides even that.
|
|
66
|
+
check_not_sudo() {
|
|
67
|
+
[ "$(id -u)" = "0" ] || return 0
|
|
68
|
+
[ -n "${SUDO_USER:-}" ] || return 0
|
|
69
|
+
if [ -n "${MOSHCODE_ALLOW_ROOT:-}" ]; then
|
|
70
|
+
info "MOSHCODE_ALLOW_ROOT set — installing as root into $MOSHCODE_HOME"
|
|
71
|
+
return 0
|
|
72
|
+
fi
|
|
73
|
+
fail "don't install moshcode with sudo.
|
|
74
|
+
|
|
75
|
+
Every path is based on \$HOME, which sudo has set to $HOME, so this would
|
|
76
|
+
install for root and leave $SUDO_USER unable to run it.
|
|
77
|
+
|
|
78
|
+
Run it as yourself instead:
|
|
79
|
+
curl -fsSL $INSTALL_URL | sh
|
|
80
|
+
|
|
81
|
+
If you really do want it system-wide, choose the paths explicitly:
|
|
82
|
+
sudo MOSHCODE_ALLOW_ROOT=1 MOSHCODE_HOME=/opt/moshcode \\
|
|
83
|
+
MOSHCODE_BIN=/usr/local/bin sh -c 'curl -fsSL $INSTALL_URL | sh'"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
check_node() {
|
|
87
|
+
command -v node >/dev/null 2>&1 || fail \
|
|
88
|
+
"Node.js 18+ is required. Install it (https://nodejs.org) and re-run."
|
|
89
|
+
_major="$(node -v 2>/dev/null | sed 's/^v//' | cut -d. -f1)"
|
|
90
|
+
[ "${_major:-0}" -ge 18 ] || fail "Node.js 18+ required, found $(node -v)."
|
|
91
|
+
ok "Node.js $(node -v)"
|
|
92
|
+
unset _major
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Resolve the download URL for the latest release tag, or fall back to main.
|
|
96
|
+
resolve_ref() {
|
|
97
|
+
if [ -n "${MOSHCODE_REF:-}" ]; then
|
|
98
|
+
echo "$MOSHCODE_REF"; return 0
|
|
99
|
+
fi
|
|
100
|
+
# Ask GitHub for the latest release tag (no auth needed for public repos).
|
|
101
|
+
_tag="$(curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" 2>/dev/null \
|
|
102
|
+
| grep '"tag_name"' | head -1 | sed 's/.*"tag_name":[[:space:]]*"\([^"]*\)".*/\1/')"
|
|
103
|
+
if [ -n "$_tag" ]; then echo "$_tag"; else echo "main"; fi
|
|
104
|
+
unset _tag
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
fetch_and_unpack() {
|
|
108
|
+
_ref="$1"
|
|
109
|
+
_url="https://codeload.github.com/$REPO/tar.gz/$_ref"
|
|
110
|
+
info "downloading moshcode@$_ref"
|
|
111
|
+
_tmp="$(mktemp -d 2>/dev/null || mktemp -d -t moshcode)"
|
|
112
|
+
if ! curl -fsSL "$_url" | tar -xz -C "$_tmp" 2>/dev/null; then
|
|
113
|
+
rm -rf "$_tmp"; fail "download failed ($_url) — check the ref/network."
|
|
114
|
+
fi
|
|
115
|
+
# Tarball extracts to a single top-level dir (e.g. moshcode-main/).
|
|
116
|
+
_src="$(find "$_tmp" -maxdepth 1 -type d -name 'moshcode-*' | head -1)"
|
|
117
|
+
[ -n "$_src" ] && [ -f "$_src/bin/moshcode.mjs" ] || { rm -rf "$_tmp"; fail "unexpected tarball layout."; }
|
|
118
|
+
rm -rf "$MOSHCODE_HOME"
|
|
119
|
+
mkdir -p "$(dirname "$MOSHCODE_HOME")"
|
|
120
|
+
mv "$_src" "$MOSHCODE_HOME"
|
|
121
|
+
rm -rf "$_tmp"
|
|
122
|
+
chmod +x "$MOSHCODE_HOME/bin/moshcode.mjs" 2>/dev/null || true
|
|
123
|
+
ok "installed to $MOSHCODE_HOME"
|
|
124
|
+
unset _ref _url _tmp _src
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
write_wrapper() {
|
|
128
|
+
mkdir -p "$MOSHCODE_BIN"
|
|
129
|
+
cat > "$WRAPPER" <<WRAP_EOF
|
|
130
|
+
#!/bin/sh
|
|
131
|
+
# moshcode wrapper — installed by $INSTALL_URL. Re-run the installer to update.
|
|
132
|
+
exec node "$MOSHCODE_HOME/bin/moshcode.mjs" "\$@"
|
|
133
|
+
WRAP_EOF
|
|
134
|
+
chmod +x "$WRAPPER"
|
|
135
|
+
ok "wrapper at $WRAPPER"
|
|
136
|
+
|
|
137
|
+
# moshscript — thin alias for `moshcode run`, so .mosh files can use
|
|
138
|
+
# #!/usr/bin/env moshscript as a shebang and run like shell scripts.
|
|
139
|
+
cat > "$SCRIPT_WRAPPER" <<SCRIPT_EOF
|
|
140
|
+
#!/bin/sh
|
|
141
|
+
# moshscript wrapper — installed by $INSTALL_URL. Re-run the installer to update.
|
|
142
|
+
exec node "$MOSHCODE_HOME/bin/moshcode.mjs" run "\$@"
|
|
143
|
+
SCRIPT_EOF
|
|
144
|
+
chmod +x "$SCRIPT_WRAPPER"
|
|
145
|
+
ok "wrapper at $SCRIPT_WRAPPER"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
ensure_path() {
|
|
149
|
+
case ":$PATH:" in *":$MOSHCODE_BIN:"*) return 0 ;; esac
|
|
150
|
+
for rc in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do
|
|
151
|
+
[ -f "$rc" ] || continue
|
|
152
|
+
grep -q "$MOSHCODE_BIN" "$rc" 2>/dev/null && continue
|
|
153
|
+
printf '\n# Added by moshcode installer\nexport PATH="%s:$PATH"\n' "$MOSHCODE_BIN" >> "$rc"
|
|
154
|
+
done
|
|
155
|
+
info "add $MOSHCODE_BIN to PATH in this shell: export PATH=\"$MOSHCODE_BIN:\$PATH\""
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# ---- commands -------------------------------------------------------------
|
|
159
|
+
run_install() {
|
|
160
|
+
printf '\n%smoshcode installer%s %s— code hard, mosh harder 🤘%s\n\n' "$BOLD" "$RESET" "$ASH" "$RESET"
|
|
161
|
+
check_not_sudo
|
|
162
|
+
need curl; need tar
|
|
163
|
+
check_node
|
|
164
|
+
_ref="$(resolve_ref)"
|
|
165
|
+
fetch_and_unpack "$_ref"
|
|
166
|
+
write_wrapper
|
|
167
|
+
ensure_path
|
|
168
|
+
printf '\n%sdone.%s run:\n' "$ACID" "$RESET"
|
|
169
|
+
printf ' moshcode # open the TUI shell\n'
|
|
170
|
+
printf ' moshcode start claude # raw engine session (use agents for autonomous)\n'
|
|
171
|
+
printf ' moshcode prd "your idea" # plan with a numbered OpenPRD\n'
|
|
172
|
+
printf ' moshcode tools # install/run UGig and CoinPay CLIs\n'
|
|
173
|
+
printf ' moshcode help\n\n'
|
|
174
|
+
unset _ref
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
run_remove() {
|
|
178
|
+
info "removing moshcode"
|
|
179
|
+
rm -f "$WRAPPER" 2>/dev/null || true
|
|
180
|
+
rm -f "$SCRIPT_WRAPPER" 2>/dev/null || true
|
|
181
|
+
rm -rf "$MOSHCODE_HOME" 2>/dev/null || true
|
|
182
|
+
ok "removed $WRAPPER, $SCRIPT_WRAPPER, and $MOSHCODE_HOME. 🤘"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
CMD="${1:-install}"
|
|
186
|
+
if [ $# -gt 0 ]; then shift; fi
|
|
187
|
+
case "$CMD" in
|
|
188
|
+
install) run_install ;;
|
|
189
|
+
update|upgrade) run_install ;; # re-fetch latest, same path
|
|
190
|
+
remove|uninstall) run_remove ;;
|
|
191
|
+
-h|--help|help)
|
|
192
|
+
sed -n '2,33p' "$0" 2>/dev/null || printf 'moshcode installer — install | update | remove\n' ;;
|
|
193
|
+
*) fail "unknown command: $CMD (try: install | update | remove)" ;;
|
|
194
|
+
esac
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "moshcode",
|
|
3
|
+
"version": "0.24.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "moshcode — a metal wrapper for coding engines and native UGig/CoinPay workflow CLIs, with OpenPRD and moshscript",
|
|
6
|
+
"bin": {
|
|
7
|
+
"moshcode": "./bin/moshcode.mjs",
|
|
8
|
+
"moshscript": "./bin/moshscript.mjs"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node bin/moshcode.mjs",
|
|
12
|
+
"demo": "node bin/moshcode.mjs run examples/alive.mosh",
|
|
13
|
+
"test": "node --test"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"bin",
|
|
17
|
+
"src",
|
|
18
|
+
"examples",
|
|
19
|
+
"prd",
|
|
20
|
+
"install.sh",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"packageManager": "pnpm@10.32.1",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@moshcoder/moshpit-dns": "^0.5.0"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
openprd: "0.2"
|
|
3
|
+
id: "0000"
|
|
4
|
+
title: "Short imperative title — start with a verb if possible"
|
|
5
|
+
status: Draft
|
|
6
|
+
authors:
|
|
7
|
+
- you@example.com
|
|
8
|
+
created: 2026-01-01
|
|
9
|
+
updated: 2026-01-01
|
|
10
|
+
repo:
|
|
11
|
+
discussion:
|
|
12
|
+
implementation:
|
|
13
|
+
tags:
|
|
14
|
+
supersedes:
|
|
15
|
+
superseded-by:
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Problem
|
|
19
|
+
|
|
20
|
+
The user/business problem, and why it matters now.
|
|
21
|
+
|
|
22
|
+
## Goals
|
|
23
|
+
|
|
24
|
+
What success looks like, as outcomes (not features).
|
|
25
|
+
|
|
26
|
+
## Non-Goals
|
|
27
|
+
|
|
28
|
+
Explicitly out of scope, to bound the work.
|
|
29
|
+
|
|
30
|
+
## Users
|
|
31
|
+
|
|
32
|
+
Who this is for; personas or segments.
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
- R1 [P0] First required capability.
|
|
37
|
+
- R2 [P1] Next capability.
|
|
38
|
+
|
|
39
|
+
## UX Notes
|
|
40
|
+
|
|
41
|
+
Flows, states, and constraints that shape the experience.
|
|
42
|
+
|
|
43
|
+
## Success Metrics
|
|
44
|
+
|
|
45
|
+
How the goals will be measured.
|
|
46
|
+
|
|
47
|
+
## Risks & Open Questions
|
|
48
|
+
|
|
49
|
+
- Known risk or decision still owed.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
openprd: "0.2"
|
|
3
|
+
id: "0001"
|
|
4
|
+
title: Wrap the UGig and CoinPay CLIs
|
|
5
|
+
status: Accepted
|
|
6
|
+
authors:
|
|
7
|
+
- anthony@chovy.com
|
|
8
|
+
created: 2026-07-13
|
|
9
|
+
updated: 2026-07-13
|
|
10
|
+
repo: https://github.com/moshcoder/moshcode
|
|
11
|
+
discussion:
|
|
12
|
+
implementation:
|
|
13
|
+
tags:
|
|
14
|
+
- cli
|
|
15
|
+
- ugig
|
|
16
|
+
- coinpay
|
|
17
|
+
- orchestration
|
|
18
|
+
supersedes:
|
|
19
|
+
superseded-by:
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Problem
|
|
23
|
+
|
|
24
|
+
MoshCode already installs and delegates to coding engines, but users and coding
|
|
25
|
+
agents must leave its workflow to discover paid work through UGig or operate the
|
|
26
|
+
CoinPay payment rail. Both products already ship broad native CLIs. Rebuilding
|
|
27
|
+
their APIs in MoshCode would duplicate authentication, command semantics, and
|
|
28
|
+
release cadence; omitting them leaves a gap between finding work, doing it, and
|
|
29
|
+
getting paid.
|
|
30
|
+
|
|
31
|
+
## Goals
|
|
32
|
+
|
|
33
|
+
- Make the native `ugig` and `coinpay` CLIs installable and discoverable through
|
|
34
|
+
MoshCode.
|
|
35
|
+
- Provide transparent top-level and TUI delegation without changing native CLI
|
|
36
|
+
behavior.
|
|
37
|
+
- Include installed external tools in MoshCode's existing upgrade workflow.
|
|
38
|
+
- Keep ownership clear: UGig owns marketplace state, CoinPay owns payment state,
|
|
39
|
+
and MoshCode only conducts the installed CLIs.
|
|
40
|
+
|
|
41
|
+
## Non-Goals
|
|
42
|
+
|
|
43
|
+
- Reimplementing UGig or CoinPay API clients or command trees in MoshCode.
|
|
44
|
+
- Adding composed `gigs`, invoice, escrow, or settlement workflows in this
|
|
45
|
+
release.
|
|
46
|
+
- Adding irreversible payment operations to moshscript.
|
|
47
|
+
- Normalizing or parsing either tool's human-readable or JSON output.
|
|
48
|
+
- Managing UGig or CoinPay credentials on MoshCode's behalf.
|
|
49
|
+
|
|
50
|
+
## Users
|
|
51
|
+
|
|
52
|
+
- Developers using MoshCode who want to find and manage UGig work from the same
|
|
53
|
+
terminal workflow.
|
|
54
|
+
- Coding agents that need machine-readable UGig output or direct CoinPay access.
|
|
55
|
+
- Operators who want one installation and upgrade surface for their coding
|
|
56
|
+
engines and adjacent workflow tools.
|
|
57
|
+
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- R1 [P0] MoshCode MUST define UGig and CoinPay in a `TOOLS` registry separate
|
|
61
|
+
from the coding-engine registry. Each entry MUST declare its executable and
|
|
62
|
+
official package installation/upgrade command.
|
|
63
|
+
- R2 [P0] `moshcode tools` MUST list both tools and report whether each native
|
|
64
|
+
executable is on `PATH`.
|
|
65
|
+
- R3 [P0] `moshcode install ugig` and `moshcode install coinpay` MUST install the
|
|
66
|
+
official npm packages; existing engine installation behavior MUST remain
|
|
67
|
+
compatible.
|
|
68
|
+
- R4 [P0] `moshcode ugig [args…]` and `moshcode coinpay [args…]` MUST pass
|
|
69
|
+
arguments, stdin, stdout, stderr, the working directory, and environment
|
|
70
|
+
through unchanged and MUST propagate the native process exit result.
|
|
71
|
+
- R5 [P0] The interactive shell MUST accept `/ugig [args…]` and
|
|
72
|
+
`/coinpay [args…]`, hand terminal control to the native CLI, and return to the
|
|
73
|
+
MoshCode prompt when it exits.
|
|
74
|
+
- R6 [P0] `moshcode upgrade` MUST update installed tools as well as installed
|
|
75
|
+
engines. `upgrade tools`, `upgrade ugig`, and `upgrade coinpay` MUST be valid
|
|
76
|
+
narrower targets.
|
|
77
|
+
- R7 [P1] Missing executables and unknown install/upgrade targets MUST produce
|
|
78
|
+
actionable errors that identify the correct MoshCode command.
|
|
79
|
+
- R8 [P1] Help text and the README MUST document installation, status,
|
|
80
|
+
passthrough, authentication ownership, and upgrade behavior.
|
|
81
|
+
- R9 [P1] Automated tests MUST cover tool resolution and transparent
|
|
82
|
+
passthrough, including arguments, standard streams, and non-zero exit codes.
|
|
83
|
+
|
|
84
|
+
## UX Notes
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
moshcode tools
|
|
88
|
+
moshcode install ugig
|
|
89
|
+
moshcode install coinpay
|
|
90
|
+
|
|
91
|
+
moshcode ugig --json gigs list
|
|
92
|
+
moshcode coinpay wallet balance
|
|
93
|
+
|
|
94
|
+
moshcode upgrade tools
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`moshcode tools` distinguishes adjacent workflow tools from `/agents` and
|
|
98
|
+
`moshcode engines`. The wrappers do not insert banners or status messages into
|
|
99
|
+
native stdout because that would corrupt JSON pipelines. Native authentication
|
|
100
|
+
continues to use each tool's config files and environment variables.
|
|
101
|
+
|
|
102
|
+
CoinPay currently requires Node.js 20 or newer while MoshCode itself supports
|
|
103
|
+
Node.js 18. Its npm installer remains the authority for enforcing that package
|
|
104
|
+
requirement; MoshCode documents it rather than changing its own runtime floor.
|
|
105
|
+
|
|
106
|
+
## Success Metrics
|
|
107
|
+
|
|
108
|
+
- All P0 requirements have automated coverage or direct CLI verification.
|
|
109
|
+
- Native `ugig` and `coinpay` help/output can be invoked through MoshCode without
|
|
110
|
+
MoshCode text appearing on stdout.
|
|
111
|
+
- A native non-zero exit code is observed unchanged by a calling shell or agent.
|
|
112
|
+
- Existing MoshCode tests and coding-engine commands continue to pass.
|
|
113
|
+
|
|
114
|
+
## Risks & Open Questions
|
|
115
|
+
|
|
116
|
+
- CoinPay's machine-readable output is not yet uniform across commands. MoshCode
|
|
117
|
+
will preserve it verbatim; CoinPay should standardize JSON-only stdout and
|
|
118
|
+
diagnostics on stderr before agents depend on every command in pipelines.
|
|
119
|
+
- Composed gig-to-invoice or escrow flows may be valuable later, but should be
|
|
120
|
+
based on observed usage and require explicit confirmation for irreversible
|
|
121
|
+
payment actions.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
openprd: "0.2"
|
|
3
|
+
id: "0002"
|
|
4
|
+
title: Separate autonomous agent and raw engine launches
|
|
5
|
+
status: Accepted
|
|
6
|
+
authors:
|
|
7
|
+
- anthony@chovy.com
|
|
8
|
+
created: 2026-07-13
|
|
9
|
+
updated: 2026-07-13
|
|
10
|
+
repo: https://github.com/moshcoder/moshcode
|
|
11
|
+
discussion:
|
|
12
|
+
implementation:
|
|
13
|
+
tags:
|
|
14
|
+
- cli
|
|
15
|
+
- agents
|
|
16
|
+
- permissions
|
|
17
|
+
- orchestration
|
|
18
|
+
supersedes:
|
|
19
|
+
superseded-by:
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Problem
|
|
23
|
+
|
|
24
|
+
MoshCode currently treats `/agents <engine>` as an ordinary native CLI launch.
|
|
25
|
+
That name implies an autonomous coding session, but the underlying engines still
|
|
26
|
+
pause for their normal permission or approval prompts. At the same time, users
|
|
27
|
+
need an explicit way to start the unmodified native CLI when they want its normal
|
|
28
|
+
safety model or need to supply their own flags.
|
|
29
|
+
|
|
30
|
+
## Goals
|
|
31
|
+
|
|
32
|
+
- Make `/agents <engine>` a predictable autonomous launch across every supported
|
|
33
|
+
coding engine.
|
|
34
|
+
- Provide `/start <engine>` as an explicit raw passthrough that injects no flags.
|
|
35
|
+
- Preserve the existing bare `moshcode <engine>` raw behavior for compatibility.
|
|
36
|
+
- Make the dangerous nature of autonomous mode visible before handoff.
|
|
37
|
+
|
|
38
|
+
## Non-Goals
|
|
39
|
+
|
|
40
|
+
- Bypassing administrator policies that disable an engine's autonomous mode.
|
|
41
|
+
- Claiming that every engine provides identical sandbox or permission semantics.
|
|
42
|
+
- Applying autonomous flags to UGig, CoinPay, installers, upgrades, or moshscript.
|
|
43
|
+
- Parsing or rewriting user-supplied native engine arguments.
|
|
44
|
+
|
|
45
|
+
## Users
|
|
46
|
+
|
|
47
|
+
- Developers who intentionally want uninterrupted agent execution in an
|
|
48
|
+
isolated or otherwise trusted workspace.
|
|
49
|
+
- Developers who want a memorable raw-start command for normal interactive use.
|
|
50
|
+
- Scripts that need the same distinction outside the MoshCode TUI.
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
- R1 [P0] Every coding-engine registry entry MUST declare the engine's current
|
|
55
|
+
autonomous or auto-approval arguments.
|
|
56
|
+
- R2 [P0] The autonomous mappings MUST be Claude
|
|
57
|
+
`--dangerously-skip-permissions`, Codex
|
|
58
|
+
`--dangerously-bypass-approvals-and-sandbox`, Gemini
|
|
59
|
+
`--approval-mode=yolo`, Aider `--yes-always`, and OpenCode `--auto`.
|
|
60
|
+
- R3 [P0] `/agents <engine> [args…]` MUST prepend the registered autonomous
|
|
61
|
+
arguments and then preserve all user-supplied arguments.
|
|
62
|
+
- R4 [P0] `/start <engine> [args…]` MUST launch the engine with only the
|
|
63
|
+
user-supplied arguments.
|
|
64
|
+
- R5 [P0] `moshcode agents <engine> [args…]` and
|
|
65
|
+
`moshcode start <engine> [args…]` MUST provide the equivalent non-TUI paths.
|
|
66
|
+
- R6 [P0] Bare `moshcode <engine> [args…]` and bare engine names in the TUI MUST
|
|
67
|
+
remain raw passthroughs for backward compatibility.
|
|
68
|
+
- R7 [P1] Agent-mode launches MUST show a warning that permission or approval
|
|
69
|
+
protections are being bypassed or auto-approved.
|
|
70
|
+
- R8 [P1] `/agents` and `moshcode agents` with no engine MUST continue listing
|
|
71
|
+
engines and their install status.
|
|
72
|
+
- R9 [P1] Automated tests MUST verify the registered mappings, autonomous
|
|
73
|
+
argument order, and raw-start behavior for every engine.
|
|
74
|
+
|
|
75
|
+
## UX Notes
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
# Autonomous: MoshCode injects the engine-specific bypass/auto-approve flag.
|
|
79
|
+
moshcode agents claude
|
|
80
|
+
moshcode agents codex --model gpt-5
|
|
81
|
+
|
|
82
|
+
# Raw: MoshCode injects nothing.
|
|
83
|
+
moshcode start claude
|
|
84
|
+
moshcode start codex --sandbox workspace-write
|
|
85
|
+
|
|
86
|
+
# Backward-compatible raw shorthand.
|
|
87
|
+
moshcode claude
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
TUI equivalents are `/agents claude`, `/start claude`, and bare `claude`.
|
|
91
|
+
`/agents` remains the status list when no engine name follows it.
|
|
92
|
+
|
|
93
|
+
The mappings are intentionally not described as identical. Claude and Codex
|
|
94
|
+
offer explicit full-bypass flags. Gemini and Aider auto-approve confirmations.
|
|
95
|
+
OpenCode's `--auto` approves requests that are not explicitly denied, so deny
|
|
96
|
+
rules remain effective.
|
|
97
|
+
|
|
98
|
+
## Success Metrics
|
|
99
|
+
|
|
100
|
+
- Each engine receives exactly its registered autonomous arguments through the
|
|
101
|
+
agent-mode path.
|
|
102
|
+
- Raw starts receive no MoshCode-injected engine arguments.
|
|
103
|
+
- Existing engine aliases, environment scrubbing, stdio, cwd, and exit behavior
|
|
104
|
+
remain intact.
|
|
105
|
+
- The full MoshCode test suite passes.
|
|
106
|
+
|
|
107
|
+
## Risks & Open Questions
|
|
108
|
+
|
|
109
|
+
- Full-bypass modes can execute destructive or prompt-injected actions. Users
|
|
110
|
+
should reserve `/agents` for isolated containers, VMs, or trusted workspaces.
|
|
111
|
+
- Engine flags can change between releases. Their own installers and help output
|
|
112
|
+
remain authoritative, and the registry mappings need maintenance when upstream
|
|
113
|
+
CLIs rename a mode.
|