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,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
openprd: "0.2"
|
|
3
|
+
id: "0005"
|
|
4
|
+
title: A hosted Moshpit resolver, for the devices that cannot run the bridge
|
|
5
|
+
status: Draft
|
|
6
|
+
authors:
|
|
7
|
+
- anthony@chovy.com
|
|
8
|
+
created: 2026-08-01
|
|
9
|
+
updated: 2026-08-01
|
|
10
|
+
repo: https://github.com/moshcoder/moshcode
|
|
11
|
+
discussion:
|
|
12
|
+
implementation: apps/pwa/src/lib/moshpit-resolvers.mjs, apps/pwa/src/routes/moshpit.mjs, src/dns.mjs
|
|
13
|
+
tags:
|
|
14
|
+
- moshpit
|
|
15
|
+
- dns
|
|
16
|
+
- infrastructure
|
|
17
|
+
- privacy
|
|
18
|
+
supersedes:
|
|
19
|
+
superseded-by:
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Problem
|
|
23
|
+
|
|
24
|
+
A Moshpit ending is not in the ICANN root, so nothing resolves it until the
|
|
25
|
+
client is told something. Today there is exactly one way to be told: run
|
|
26
|
+
`moshcode dns enable`, which installs a local bridge and points the machine's
|
|
27
|
+
resolver at it.
|
|
28
|
+
|
|
29
|
+
That works on a laptop or a VPS. It is unavailable on the devices where most
|
|
30
|
+
people would actually meet a Moshpit name:
|
|
31
|
+
|
|
32
|
+
- a **phone**, which cannot run a daemon or edit `resolved.conf.d`
|
|
33
|
+
- a **router**, where you can set a DNS server and nothing else
|
|
34
|
+
- **someone else's machine** — the person you sent the link to
|
|
35
|
+
|
|
36
|
+
For all of them the only answer is `pit.moshcode.sh/n/<name>`, which fetches the
|
|
37
|
+
origin server-side and hands back the page. It works, and it is not resolution:
|
|
38
|
+
the URL bar reads `pit.moshcode.sh`, not `chovy.hacker`. The name never becomes
|
|
39
|
+
the visitor's address, which is the entire point of holding one.
|
|
40
|
+
|
|
41
|
+
The infrastructure for the missing piece is already half-built and unused.
|
|
42
|
+
`MOSHPIT_DNS_RESOLVERS` and `MOSHPIT_DOH_URL` are read, validated as real
|
|
43
|
+
addresses, and rendered on `/pit/dns` — and both are unset in production, so the
|
|
44
|
+
page publishes nothing. The shop window was built before the shop.
|
|
45
|
+
|
|
46
|
+
This PRD is deliberately **not** a replacement for the local bridge. It is the
|
|
47
|
+
answer for clients that cannot run one, and the difference matters because the
|
|
48
|
+
tradeoff is real and permanent: a hosted resolver sees every DNS query the
|
|
49
|
+
device makes.
|
|
50
|
+
|
|
51
|
+
## Goals
|
|
52
|
+
|
|
53
|
+
- A Moshpit name resolves on a device that can only be handed a DNS server.
|
|
54
|
+
- The URL bar keeps the name. `http://chovy.hacker/` stays `chovy.hacker`.
|
|
55
|
+
- Non-Moshpit lookups are answered correctly and are not the product.
|
|
56
|
+
- The privacy cost is stated plainly, in the UI, before anyone opts in.
|
|
57
|
+
- An outage degrades to "Moshpit names stop working", never "the internet stops
|
|
58
|
+
working", for as long as that is within our control.
|
|
59
|
+
|
|
60
|
+
## Non-Goals
|
|
61
|
+
|
|
62
|
+
- **Replacing the local bridge.** Where a bridge can run it stays the better
|
|
63
|
+
answer: no third party sees the queries, no round trip, no shared outage.
|
|
64
|
+
`moshcode dns enable` remains the recommended path and the docs say so.
|
|
65
|
+
- **Being a general-purpose public resolver.** We are not competing with
|
|
66
|
+
1.1.1.1. Forwarding exists so Moshpit names can resolve, not as a service.
|
|
67
|
+
- **Logging queries for analytics.** See Requirements — this is the one place
|
|
68
|
+
where the tempting feature is the one that kills the product.
|
|
69
|
+
- **DNSSEC-signing the Moshpit zone.** Out of scope for v1; the endings are not
|
|
70
|
+
in the root, so there is no chain to anchor to.
|
|
71
|
+
|
|
72
|
+
## Users
|
|
73
|
+
|
|
74
|
+
**Someone sent a link.** They open `http://seo.rank/` on a phone. Today: a
|
|
75
|
+
browser error, or a `pit.moshcode.sh` URL. With this: the page, at its own name.
|
|
76
|
+
|
|
77
|
+
**A household or office.** One DNS setting on the router, and every device on
|
|
78
|
+
the network resolves Moshpit names with nothing installed on any of them.
|
|
79
|
+
|
|
80
|
+
**A name holder demonstrating one.** The reason to hold `chovy.hacker` is that
|
|
81
|
+
it is an address you can give people. Today giving it away requires asking them
|
|
82
|
+
to install software first.
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
### R1 — Two protocols, both public
|
|
87
|
+
|
|
88
|
+
`Do53` (plain UDP/TCP 53) for routers and OS settings, and **DNS-over-HTTPS**
|
|
89
|
+
for phones and browsers, which increasingly will not accept anything else.
|
|
90
|
+
iOS and Android both accept a DoH profile; neither will run our daemon.
|
|
91
|
+
|
|
92
|
+
DoH is the one that unlocks phones, so it is not optional.
|
|
93
|
+
|
|
94
|
+
### R2 — Anycast or nothing
|
|
95
|
+
|
|
96
|
+
A single box is a single point of failure for the DNS of every device pointed
|
|
97
|
+
at it. If the deployment cannot be multi-region behind one address, this ships
|
|
98
|
+
as "best effort, do not set it as your only resolver" and says so in the UI.
|
|
99
|
+
|
|
100
|
+
### R3 — Forwarding is the dangerous part
|
|
101
|
+
|
|
102
|
+
The resolver answers Moshpit endings from the registry and forwards everything
|
|
103
|
+
else. That forwarding is what makes it usable as a device's only DNS server —
|
|
104
|
+
and what makes it a privacy problem, a latency tax, and a shared outage.
|
|
105
|
+
|
|
106
|
+
Three requirements follow, and R3.3 is the one worth arguing about:
|
|
107
|
+
|
|
108
|
+
- **R3.1** — the claimed-ending gate from `isOurs` applies here identically.
|
|
109
|
+
`google.com` has two labels exactly like `blue.eggs`; only an ending someone
|
|
110
|
+
has actually claimed is ours. An unknown ending set means *not* ours.
|
|
111
|
+
- **R3.2** — forwarded answers are relayed unmodified. No injected records, no
|
|
112
|
+
rewritten NXDOMAIN, no "helpful" search page. The moment a resolver edits
|
|
113
|
+
answers it is spyware with a nice landing page.
|
|
114
|
+
- **R3.3** — **no query logging beyond aggregate counters.** No per-query
|
|
115
|
+
storage of name, source address, or the pair. This is the requirement that
|
|
116
|
+
will be under pressure the first time someone asks "which endings are people
|
|
117
|
+
looking up?" — and the honest answer is that we cannot know without becoming
|
|
118
|
+
the thing the local bridge exists to avoid. Counters (queries/sec, hit rate,
|
|
119
|
+
error rate) are fine. The tuple is not.
|
|
120
|
+
|
|
121
|
+
### R4 — Say the cost before the click
|
|
122
|
+
|
|
123
|
+
`/pit/dns` publishes the addresses. It must also state, in the same visual
|
|
124
|
+
weight as the addresses themselves:
|
|
125
|
+
|
|
126
|
+
> This resolver sees every DNS lookup your device makes, not just Moshpit ones.
|
|
127
|
+
> If you can run `moshcode dns enable`, do that instead — it keeps your lookups
|
|
128
|
+
> on your own machine.
|
|
129
|
+
|
|
130
|
+
A page that lists an IP with no context gets pasted into a router by someone who
|
|
131
|
+
has not thought about it. That is the failure mode to design against.
|
|
132
|
+
|
|
133
|
+
### R5 — Reuse the bridge, do not fork it
|
|
134
|
+
|
|
135
|
+
The hosted resolver is the same code as `src/dns.mjs` with upstreams
|
|
136
|
+
configured, deployed. The forwarding, the ending gate, the NODATA/NXDOMAIN
|
|
137
|
+
distinction and the AAAA support all already exist and are tested. A second
|
|
138
|
+
implementation would drift from the first, which is the failure this codebase
|
|
139
|
+
has already had five times over with one regex.
|
|
140
|
+
|
|
141
|
+
### R6 — Never the default
|
|
142
|
+
|
|
143
|
+
Nothing in `moshcode dns enable`, the CLI, or the extension silently points at
|
|
144
|
+
the hosted resolver. It is a documented address a person chooses to use. A
|
|
145
|
+
resolver that installs itself as your DNS without asking is malware behaviour
|
|
146
|
+
regardless of intent.
|
|
147
|
+
|
|
148
|
+
## UX Notes
|
|
149
|
+
|
|
150
|
+
`/pit/dns` already renders `.pit-addrs` cards for published resolvers, so the
|
|
151
|
+
page work is mostly copy plus the DoH URL. The order should be:
|
|
152
|
+
|
|
153
|
+
1. **`moshcode dns enable`** — recommended, keeps lookups local
|
|
154
|
+
2. **`pit.moshcode.sh/n/<name>`** — works with nothing installed, URL changes
|
|
155
|
+
3. **the hosted resolver** — for devices that cannot do (1), with R4's warning
|
|
156
|
+
|
|
157
|
+
Today the page has only (1) and publishes nothing for (3).
|
|
158
|
+
|
|
159
|
+
## Success Metrics
|
|
160
|
+
|
|
161
|
+
- A stock phone, given only a DoH profile, loads `http://chovy.hacker/` with
|
|
162
|
+
`chovy.hacker` in the URL bar.
|
|
163
|
+
- Resolver p50 latency for a forwarded (non-Moshpit) query stays within ~10ms of
|
|
164
|
+
the device's previous resolver, or the tax is visible enough that people turn
|
|
165
|
+
it off.
|
|
166
|
+
- Zero per-query records in storage, demonstrable from the deployment config
|
|
167
|
+
rather than from a policy document.
|
|
168
|
+
|
|
169
|
+
## Risks & Open Questions
|
|
170
|
+
|
|
171
|
+
**The privacy tradeoff is not fixable, only disclosed.** Anyone using this hands
|
|
172
|
+
us their full DNS history. R3.3 and R4 are mitigations, not solutions. If that
|
|
173
|
+
is unacceptable, the honest outcome is to not ship this and leave `/n/` as the
|
|
174
|
+
answer for phones.
|
|
175
|
+
|
|
176
|
+
**Shared outage.** A device with this as its only DNS server loses the whole
|
|
177
|
+
internet when we go down, not just Moshpit names. R2 exists for this and may
|
|
178
|
+
well be the reason to delay.
|
|
179
|
+
|
|
180
|
+
**Abuse.** An open forwarding resolver is a DDoS amplifier. Rate limiting and
|
|
181
|
+
response-size limits are required before anything is published, and this is not
|
|
182
|
+
optional or deferrable — an open resolver is found by scanners in hours.
|
|
183
|
+
|
|
184
|
+
**Does the demand exist?** The cheapest version of this experiment is to publish
|
|
185
|
+
nothing and instead measure how often `/n/` is loaded from mobile user agents.
|
|
186
|
+
If nobody is meeting Moshpit names on phones, this is infrastructure and risk
|
|
187
|
+
bought for an audience that is not there.
|
|
188
|
+
|
|
189
|
+
**Open:** does the ending gate consult the registry per query, or hold a cached
|
|
190
|
+
ending set refreshed on an interval? Per query is simpler and always current;
|
|
191
|
+
cached is faster and survives a registry outage. The local bridge faces the same
|
|
192
|
+
choice and has not resolved it either.
|
package/prd/0006-help.md
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
---
|
|
2
|
+
openprd: "0.2"
|
|
3
|
+
id: "0006"
|
|
4
|
+
title: "--help"
|
|
5
|
+
status: Draft
|
|
6
|
+
authors:
|
|
7
|
+
- anthony@chovy.com
|
|
8
|
+
created: 2026-08-01
|
|
9
|
+
updated: 2026-08-01
|
|
10
|
+
repo: https://github.com/moshcoder/moshcode
|
|
11
|
+
discussion:
|
|
12
|
+
implementation: src/cli-schema.mjs, src/help.mjs, bin/moshcode.mjs, src/tui.mjs, src/integrations.mjs, src/console.mjs, src/dns.mjs, src/completion.mjs, test/help.test.mjs
|
|
13
|
+
tags:
|
|
14
|
+
- cli
|
|
15
|
+
- help
|
|
16
|
+
- dx
|
|
17
|
+
- discoverability
|
|
18
|
+
supersedes:
|
|
19
|
+
superseded-by:
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Problem
|
|
23
|
+
|
|
24
|
+
`--help` is the first command anyone types and the last one we maintain. In
|
|
25
|
+
moshcode today it is a single 87-line template literal — `help()` in
|
|
26
|
+
`bin/moshcode.mjs:125-211` — hand-written prose that is neither derived from the
|
|
27
|
+
command table nor reachable from anywhere except the top level. Four things are
|
|
28
|
+
broken, and one of them writes to disk.
|
|
29
|
+
|
|
30
|
+
**1. `--help` only works at `argv[2]`.** Every subcommand handles it by accident,
|
|
31
|
+
and each accident is different:
|
|
32
|
+
|
|
33
|
+
| command | today | |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `moshcode prd --help` | **creates `prd/0006---help.md`, commits it, and hands it to Claude to author** | side effect |
|
|
36
|
+
| `moshcode run --help` | `moshcode run: unknown option --help`, exit 1 | error |
|
|
37
|
+
| `moshcode mcp --help` | `✗ unknown mcp verb "--help" — try install, add, catalog, or list`, exit 1 | error |
|
|
38
|
+
| `moshcode skill --help` | `✗ unknown skill verb "--help"`, exit 1 | error |
|
|
39
|
+
| `moshcode completion --help` | `unsupported shell "--help"`, exit 1 | error |
|
|
40
|
+
| `moshcode console --help` | usage on **stderr**, exit 1 | wrong stream + code |
|
|
41
|
+
| `moshcode install --help` | usage on **stderr**, exit 0 | wrong stream |
|
|
42
|
+
| `moshcode commands --help` | silently ignores the flag and runs | ignored |
|
|
43
|
+
| `moshcode dns --help` | correct usage, stdout, exit 0 | the one that works |
|
|
44
|
+
|
|
45
|
+
`moshcode prd --help` is the sharp edge: `--help` is parsed as the PRD *idea*, so
|
|
46
|
+
asking for help publishes a document. (It is how this PRD's own file got its
|
|
47
|
+
title.)
|
|
48
|
+
|
|
49
|
+
**2. The help text has already drifted from the CLI.** `moshcode dns` and
|
|
50
|
+
`moshcode version` are dispatched in `bin/moshcode.mjs` and present in
|
|
51
|
+
`CORE_CLI_COMMANDS` (`src/cli-schema.mjs`) and in shell completion — and appear
|
|
52
|
+
nowhere in `moshcode help`. Neither do the aliases (`where`, `remove`, `update`,
|
|
53
|
+
`skills`, `agent`), nor `uninstall --yes` / `--dry-run`. `src/cli-schema.mjs`
|
|
54
|
+
already exists as the structured command table with descriptions, and
|
|
55
|
+
`src/completion.mjs` already derives bash/zsh/fish completion from it — help is
|
|
56
|
+
the one consumer that re-types everything by hand.
|
|
57
|
+
|
|
58
|
+
**3. There is no help at any level below the top.** `moshcode help mcp` prints
|
|
59
|
+
the same 127-line wall as `moshcode help`. There is no synopsis, no flag list,
|
|
60
|
+
and no example for any individual command, so the flags that exist only in code
|
|
61
|
+
(`--json`, `--bind`, `--ttyd`, `--max`, `--dry-run`, `--device`, `--browser`,
|
|
62
|
+
`--yes`, `--`) are undiscoverable without reading the source.
|
|
63
|
+
|
|
64
|
+
**4. Failure prints the wall.** `moshcode bogus` dumps all 127 lines — to
|
|
65
|
+
**stdout**, so it pollutes pipes — and exits 1, with no "did you mean install?".
|
|
66
|
+
28 of those lines exceed 80 columns and wrap badly in a narrow terminal.
|
|
67
|
+
|
|
68
|
+
The pit has the same problem in a second copy: `printHelp()` in `src/tui.mjs`
|
|
69
|
+
hardcodes `/railway /gh /supabase /doppler /doctl /turso /tailscale` immediately
|
|
70
|
+
below a `printTools()` whose own comment explains why hardcoding the tool roster
|
|
71
|
+
goes stale. `/help` also omits `/logout` and `/uninstall`, and lists no `/dns` or
|
|
72
|
+
`/console` because the TUI never implemented them.
|
|
73
|
+
|
|
74
|
+
This matters now because moshcode's surface just tripled — engines, eleven
|
|
75
|
+
workflow tools, MCP/skill fan-out ([[0003-cross-engine-mcp-and-skill-installation]]),
|
|
76
|
+
PRDs, `console`, `dns`, and the moshscript vocabulary
|
|
77
|
+
([[0004-moshscript-run-programmable-moshcode]]) — and because the primary
|
|
78
|
+
consumer of `--help` is now an *agent*. A coding engine driving moshcode reads
|
|
79
|
+
`--help` to learn the interface; it gets a wall on stdout, an exit 1, or a
|
|
80
|
+
committed PRD.
|
|
81
|
+
|
|
82
|
+
## Goals
|
|
83
|
+
|
|
84
|
+
- `--help` is safe, uniform, and total: the same flag works at every level, on
|
|
85
|
+
every command and subcommand, and never changes anything on disk or over the
|
|
86
|
+
network.
|
|
87
|
+
- A newcomer can discover any moshcode capability — including every flag — from
|
|
88
|
+
the terminal alone, without opening `README.md` or the source.
|
|
89
|
+
- Help text can no longer drift from the CLI, because it is rendered from the
|
|
90
|
+
same schema the dispatcher and shell completion already use.
|
|
91
|
+
- An agent can consume the interface mechanically (`--json`) as reliably as it
|
|
92
|
+
consumes `moshcode engines --json` and `moshcode commands --json`.
|
|
93
|
+
- Failure is short and actionable: a mistyped command yields one line of
|
|
94
|
+
correction and one usage block, not a screenful.
|
|
95
|
+
- The pit and the CLI describe the same product, from one source.
|
|
96
|
+
|
|
97
|
+
## Non-Goals
|
|
98
|
+
|
|
99
|
+
- A CLI framework. No commander/yargs/oclif; moshcode's hand-rolled dispatch and
|
|
100
|
+
zero-runtime-dependency posture stay ([[0004-moshscript-run-programmable-moshcode]]).
|
|
101
|
+
- Restructuring the command surface. This PRD documents what exists; renaming
|
|
102
|
+
verbs, changing flags, or adding TUI commands (`/dns`, `/console`) is separate
|
|
103
|
+
work. Where help exposes an omission, help notes it — it doesn't fix it.
|
|
104
|
+
- Localization / i18n. English, metal, one voice.
|
|
105
|
+
- `man` pages, HTML docs, or a docs site. `--markdown` output (R13) is a
|
|
106
|
+
build-time convenience, not a docs pipeline.
|
|
107
|
+
- Help for the *wrapped* tools. `moshcode gh --help` is and remains a byte-exact
|
|
108
|
+
passthrough to `gh --help`; moshcode never intercepts a tool's own help.
|
|
109
|
+
- Rewriting `README.md` prose. Its command listings become schema-checked; its
|
|
110
|
+
narrative stays hand-written.
|
|
111
|
+
|
|
112
|
+
## Users
|
|
113
|
+
|
|
114
|
+
- **The first-run human** who installs moshcode and types `moshcode --help`.
|
|
115
|
+
They need one screen, not 127 lines, and a way to drill in.
|
|
116
|
+
- **The returning user** who knows the verb and forgot the flag — "was it
|
|
117
|
+
`--bind` or `--host`?" — and wants `moshcode console --help` to answer in four
|
|
118
|
+
lines.
|
|
119
|
+
- **The coding engine** (Claude, Codex, Gemini, opencode, aider) that moshcode
|
|
120
|
+
itself launched, now shelling back into `moshcode --help` to learn what it can
|
|
121
|
+
drive. Structured output, correct exit codes, and stdout/stderr discipline are
|
|
122
|
+
the whole interface for this user.
|
|
123
|
+
- **The moshscript author** who needs the vocabulary and its call signatures —
|
|
124
|
+
today split across `moshcode commands`, the tail of `moshcode help`, and
|
|
125
|
+
`README.md`.
|
|
126
|
+
- **The contributor** adding an engine, a tool, or a verb, who must not have to
|
|
127
|
+
remember that the roster is written down in five places.
|
|
128
|
+
|
|
129
|
+
## Requirements
|
|
130
|
+
|
|
131
|
+
- R1 [P0] `--help`, `-h`, and `help` MUST be recognized *before* any dispatch or
|
|
132
|
+
argument parsing, at every level: `moshcode --help`, `moshcode <cmd> --help`,
|
|
133
|
+
and `moshcode <cmd> <verb> --help` (e.g. `mcp install --help`). Recognition
|
|
134
|
+
MUST NOT depend on flag position among that level's own arguments.
|
|
135
|
+
- R2 [P0] Help MUST be free of side effects. `moshcode prd --help` MUST print
|
|
136
|
+
usage and MUST NOT call `createPrd()`, write to `prd/`, git-commit, or spawn an
|
|
137
|
+
engine. A regression test MUST assert `prd/` is unchanged after `prd --help`,
|
|
138
|
+
`prd -h`, and `prd help`. Equivalent no-side-effect assertions MUST cover
|
|
139
|
+
`install`, `uninstall`, `upgrade`, `mcp`, `skill`, `console`, `dns`, and `run`.
|
|
140
|
+
- R3 [P0] Stream and exit-code discipline MUST be uniform:
|
|
141
|
+
- help asked for explicitly → **stdout**, exit **0**;
|
|
142
|
+
- help printed because of a usage error → **stderr**, exit **1**, and the
|
|
143
|
+
message MUST be the offending command's own usage block (target: ≤ 12
|
|
144
|
+
lines), never the full top-level wall.
|
|
145
|
+
This fixes `console --help` (stderr/exit 1), `install --help` (stderr), and
|
|
146
|
+
`moshcode bogus` (127 lines to stdout).
|
|
147
|
+
- R4 [P0] Per-command help MUST exist for every dispatched command, reachable
|
|
148
|
+
both as `moshcode <cmd> --help` and `moshcode help <cmd>`. Each MUST render:
|
|
149
|
+
one-line description, synopsis with positional arguments, every flag it
|
|
150
|
+
actually parses with its default, at least one runnable example, and a
|
|
151
|
+
`see also` line. Sub-verbs (`mcp install`, `skill list`, `dns enable`,
|
|
152
|
+
`console serve`, `upgrade engines`) MUST each get their own.
|
|
153
|
+
- R5 [P0] Help MUST be rendered from a single structured schema, not prose. The
|
|
154
|
+
existing `CORE_CLI_COMMANDS` in `src/cli-schema.mjs` MUST be extended with
|
|
155
|
+
`synopsis`, `args`, `flags`, `examples`, `aliasOf`, and `seeAlso`, and a new
|
|
156
|
+
`src/help.mjs` MUST own rendering. The 87-line template literal at
|
|
157
|
+
`bin/moshcode.mjs:125-211` MUST be deleted, not merely supplemented. Engine and
|
|
158
|
+
tool rosters MUST continue to be derived from `ENGINES` / `TOOLS`, and the
|
|
159
|
+
moshscript vocabulary from `moshVocabulary()`, exactly as `help()` does today.
|
|
160
|
+
- R6 [P0] A drift test MUST make missing help a build failure, mirroring the
|
|
161
|
+
existing `completion schema covers every explicitly dispatched CLI command`
|
|
162
|
+
test (`test/completion.test.mjs:71`): every `cmd === "…"` literal in
|
|
163
|
+
`bin/moshcode.mjs`, every entry in `MCP_VERBS` / `SKILL_VERBS` /
|
|
164
|
+
`UPGRADE_TARGETS`, every key of `ENGINES` and `TOOLS`, and every registered
|
|
165
|
+
moshscript verb MUST have a schema entry with a non-empty description.
|
|
166
|
+
- R7 [P0] The commands missing from today's help MUST be covered by the schema
|
|
167
|
+
and therefore appear: `dns` (and its `enable`/`disable`/`tlds`/`resolve`
|
|
168
|
+
sub-verbs), `version`, and every alias — `where`→`pwd`, `remove`→`uninstall`,
|
|
169
|
+
`update`→`upgrade`, `skills`→`skill`, `agent`/`engines`→`agents`, `-v`/`-h`.
|
|
170
|
+
Aliases MUST be rendered as aliases, not duplicated as peers.
|
|
171
|
+
- R8 [P0] Currently undocumented flags MUST be documented by R4's flag lists, at
|
|
172
|
+
minimum: `--json` (`engines`, `tools`, `commands`, `mcp list`, `skill list`),
|
|
173
|
+
`run --max N|-n N` (default 3), `run --dry-run`, `run --` and `-` for stdin,
|
|
174
|
+
`uninstall --yes|-y` and `--dry-run`, `login --device|-d` and `--browser|-b`,
|
|
175
|
+
`console --port|--ttyd|--bind|--url`, `mcp --name|-t|-e|-H|--`, and
|
|
176
|
+
`dns --port|--registry`.
|
|
177
|
+
- R9 [P1] `moshcode help --json` and `moshcode <cmd> --help --json` MUST emit the
|
|
178
|
+
help model as JSON on stdout, exit 0, with no decoration — the same contract
|
|
179
|
+
`engines --json`, `tools --json`, and `commands --json` already honor (and the
|
|
180
|
+
same reason `moshcode tools` suppresses its trailing note under `--json`).
|
|
181
|
+
This is the agent-facing interface.
|
|
182
|
+
- R10 [P1] Top-level `moshcode --help` MUST fit one screen: a target of ≤ 40
|
|
183
|
+
lines covering usage, grouped command names with one-line descriptions, and a
|
|
184
|
+
pointer to `moshcode help <command>`. Full output MUST remain available via
|
|
185
|
+
`moshcode help --all`. All rendered help MUST wrap at 80 columns (127 lines
|
|
186
|
+
today, 28 of them over 80).
|
|
187
|
+
- R11 [P1] An unrecognized command or sub-verb MUST print, to stderr with exit 1,
|
|
188
|
+
a one-line error, a nearest-match suggestion computed from the schema
|
|
189
|
+
(`moshcode instal` → `did you mean install?`), and a pointer to
|
|
190
|
+
`moshcode help` — instead of the current full-wall dump. The suggestion MUST
|
|
191
|
+
draw on the same command set completion uses, so the two never disagree.
|
|
192
|
+
- R12 [P1] The pit MUST render from the same schema. `printHelp()` in
|
|
193
|
+
`src/tui.mjs` MUST stop hardcoding tool names (`/ugig /coinpay /railway /gh
|
|
194
|
+
/supabase /doppler /doctl /turso /tailscale`) and derive them from `TOOLS` as
|
|
195
|
+
`printTools()` already does; `/help <command>` and `/<command> --help` MUST
|
|
196
|
+
work; and `/help` MUST list every dispatched pit command, including the
|
|
197
|
+
currently omitted `/logout` and `/uninstall`. Where a CLI command has no pit
|
|
198
|
+
equivalent (`dns`, `console`, `completion`), `/help` MUST say so rather than
|
|
199
|
+
imply it exists.
|
|
200
|
+
- R13 [P1] `README.md`'s command listings MUST be checked against the schema by a
|
|
201
|
+
test (or generated from it via `moshcode help --markdown`), so a new verb
|
|
202
|
+
cannot ship documented in one place and absent in the other.
|
|
203
|
+
- R14 [P2] moshscript vocabulary help: `moshcode help <verb>` MUST resolve
|
|
204
|
+
moshscript verbs too (`moshcode help ai`, `help ask`, `help notify`), rendering
|
|
205
|
+
a call signature — `ai(prompt, { engine })` — from an optional `usage` field on
|
|
206
|
+
the registry command object (`src/registry.mjs`), alongside its existing
|
|
207
|
+
`summary`. Verbs without a `usage` fall back to the summary.
|
|
208
|
+
- R15 [P2] Rendering MUST respect the terminal: honor `NO_COLOR` and non-TTY
|
|
209
|
+
stdout by emitting plain text (the CLI's `help()` is already plain; the pit's
|
|
210
|
+
is not), and MUST NOT paginate or require a pager.
|
|
211
|
+
- R16 [P2] `moshcode completion` MUST offer help topics after `moshcode help `,
|
|
212
|
+
so tab-completion and `help` share the same discoverability surface.
|
|
213
|
+
|
|
214
|
+
## UX Notes
|
|
215
|
+
|
|
216
|
+
Top level — one screen, grouped, with a way in (R10):
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
moshcode — metal scripting toolkit 🤘
|
|
220
|
+
|
|
221
|
+
usage: moshcode [command] [args…] no command → open the mosh pit
|
|
222
|
+
|
|
223
|
+
engines agents · start · install · uninstall · upgrade · engines
|
|
224
|
+
tools tools · ugig · coinpay · c0mpute · secrets · gh · railway · …
|
|
225
|
+
extend mcp · skill · commands · completion
|
|
226
|
+
script run · prd
|
|
227
|
+
account login · whoami · logout · console
|
|
228
|
+
system dns · pwd · version · help
|
|
229
|
+
|
|
230
|
+
moshcode help <command> drill into one (flags, examples)
|
|
231
|
+
moshcode help --all the whole wall
|
|
232
|
+
moshcode help --json the machine-readable model
|
|
233
|
+
|
|
234
|
+
engines are installed and driven by moshcode — 🤘 no bugs, only features
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Per-command help — the shape every command gets (R4), and the case that today
|
|
238
|
+
publishes a document instead:
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
$ moshcode prd --help
|
|
242
|
+
moshcode prd — publish the next numbered PRD (OpenPRD) and author it
|
|
243
|
+
|
|
244
|
+
usage:
|
|
245
|
+
moshcode prd list existing PRDs
|
|
246
|
+
moshcode prd <idea…> publish prd/NNNN-slug.md (status: Draft) and hand
|
|
247
|
+
it to an installed engine to author
|
|
248
|
+
|
|
249
|
+
examples:
|
|
250
|
+
moshcode prd # the index
|
|
251
|
+
moshcode prd "a --help that works" # publish + author
|
|
252
|
+
|
|
253
|
+
see also: moshcode help run · prd/README.md · https://github.com/profullstack/logicsrc/blob/master/docs/openprd.md
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Failure — short, corrective, on stderr, exit 1 (R3, R11):
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
$ moshcode instal claude
|
|
260
|
+
✗ unknown command "instal" — did you mean install?
|
|
261
|
+
moshcode help list commands
|
|
262
|
+
$ echo $?
|
|
263
|
+
1
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Sub-verb help, reachable at depth (R1):
|
|
267
|
+
|
|
268
|
+
```
|
|
269
|
+
$ moshcode mcp install --help
|
|
270
|
+
moshcode mcp install — register an MCP server across every engine that supports it
|
|
271
|
+
|
|
272
|
+
usage:
|
|
273
|
+
moshcode mcp install <url> remote server (http/sse)
|
|
274
|
+
moshcode mcp install --name <n> -- <cmd…> local stdio server
|
|
275
|
+
moshcode mcp install <catalog-name> e.g. porkbun, sentry
|
|
276
|
+
|
|
277
|
+
flags:
|
|
278
|
+
--name <n> override the derived server name
|
|
279
|
+
-t, --transport http | sse | stdio (default: inferred from target)
|
|
280
|
+
-e, --env K=V repeatable
|
|
281
|
+
-H, --header 'K: V' repeatable
|
|
282
|
+
-- everything after this is the server's argv
|
|
283
|
+
|
|
284
|
+
fans out to: claude, gemini, codex, opencode (moshcode mcp list)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Constraints that shape all of it: the voice stays irreverent-metal (`the pit`,
|
|
288
|
+
`no bugs only features`, 🤘) but never at the cost of scanability — emoji are
|
|
289
|
+
decoration on headers, never load-bearing in a synopsis. Help is the one command
|
|
290
|
+
guaranteed to run before anything is installed and before anyone has logged in,
|
|
291
|
+
so it MUST NOT touch the network, read credentials, or probe for binaries beyond
|
|
292
|
+
the local `engineStatus()` / `toolStatus()` checks help already makes. And
|
|
293
|
+
because `moshcode run --help` and `./script.mosh --help` are different questions
|
|
294
|
+
(the runner's help vs. the script's argv), the runner MUST claim `--help` only
|
|
295
|
+
before the script filename; after it, `--help` belongs to the script (`argv`, per
|
|
296
|
+
[[0004-moshscript-run-programmable-moshcode]] R13).
|
|
297
|
+
|
|
298
|
+
## Success Metrics
|
|
299
|
+
|
|
300
|
+
- **Zero side effects from help.** `prd --help` leaves `git status` clean;
|
|
301
|
+
asserted in tests (R2). This is the one that must be true on day one.
|
|
302
|
+
- **Total coverage, enforced.** The R6 drift test passes with an empty allowlist:
|
|
303
|
+
every dispatched command, sub-verb, alias, engine, tool, and moshscript verb
|
|
304
|
+
has help. Adding a command without help fails `pnpm test`.
|
|
305
|
+
- **Uniformity.** For all N dispatched commands, `moshcode <cmd> --help` exits 0
|
|
306
|
+
and writes to stdout — today 5 of 9 sampled commands exit 1, and 2 more write
|
|
307
|
+
to stderr.
|
|
308
|
+
- **Flag discoverability.** Every flag parsed anywhere in `bin/moshcode.mjs`,
|
|
309
|
+
`src/console.mjs`, `src/dns.mjs`, and `src/integrations.mjs` appears in some
|
|
310
|
+
help output; verified by a test that greps the parsers for flag literals and
|
|
311
|
+
looks each one up in the schema.
|
|
312
|
+
- **Fits the screen.** `moshcode --help` ≤ 40 lines and no line over 80 columns
|
|
313
|
+
(127 lines / 28 over-length today); `moshcode help --all` unbounded.
|
|
314
|
+
- **Agent-consumable.** `moshcode help --json` parses, and a round-trip test
|
|
315
|
+
confirms every command in the JSON is dispatchable and every dispatched
|
|
316
|
+
command is in the JSON.
|
|
317
|
+
- **One source.** `grep -c "usage:" bin/moshcode.mjs src/tui.mjs` trends to 0 as
|
|
318
|
+
the hand-written blocks move into `src/cli-schema.mjs`.
|
|
319
|
+
- **README can't drift.** R13's test passes against the committed `README.md`.
|
|
320
|
+
|
|
321
|
+
## Risks & Open Questions
|
|
322
|
+
|
|
323
|
+
- **Losing the wall people grep.** `moshcode help | grep console` works today
|
|
324
|
+
precisely *because* everything is on one screen dump. Collapsing to a one-page
|
|
325
|
+
overview (R10) breaks that muscle memory. Mitigation: `moshcode help --all`
|
|
326
|
+
keeps the full text, and `--json` is the better grep target. Open: should
|
|
327
|
+
`--all` be the default when stdout is not a TTY, so pipes keep seeing
|
|
328
|
+
everything?
|
|
329
|
+
- **Schema verbosity.** Turning `CORE_CLI_COMMANDS` into full help entries makes
|
|
330
|
+
`src/cli-schema.mjs` the largest file describing the smallest amount of
|
|
331
|
+
behavior, and every new flag becomes a two-place edit (parser + schema).
|
|
332
|
+
R6/R8's tests are what make the second place non-optional — but a test that
|
|
333
|
+
greps parsers for flag literals is itself brittle. Open: is a stricter seam
|
|
334
|
+
worth it, where the schema *is* the parser (each command declares its flags and
|
|
335
|
+
the dispatcher parses from that), or does that quietly become the CLI framework
|
|
336
|
+
this PRD calls a Non-Goal?
|
|
337
|
+
- **`moshcode <tool> --help` ambiguity.** `moshcode gh --help` must reach `gh`,
|
|
338
|
+
not moshcode (Non-Goals) — but then there is no way to ask moshcode how *it*
|
|
339
|
+
wraps `gh`. Proposal: `moshcode help gh` answers the wrapper question and
|
|
340
|
+
`moshcode gh --help` passes through. Needs a decision, and it is the single
|
|
341
|
+
most likely source of user confusion in this design.
|
|
342
|
+
- **Same ambiguity for engines.** `moshcode claude --help` is a raw launch
|
|
343
|
+
shorthand that will pass `--help` to Claude Code. Same proposed split, same
|
|
344
|
+
risk.
|
|
345
|
+
- **`moshcode help` with an unknown topic.** Exit 0 with the overview, or exit 1
|
|
346
|
+
with a suggestion? R11 implies the latter for commands; `help` itself asking a
|
|
347
|
+
question is arguably not an error. Undecided.
|
|
348
|
+
- **The pit's missing commands.** R12 exposes that `/dns` and `/console` don't
|
|
349
|
+
exist in the TUI. Saying so in `/help` is honest but reads as a to-do list in
|
|
350
|
+
the product. Do we ship the disclosure, or implement the two commands first
|
|
351
|
+
(out of scope here)?
|
|
352
|
+
- **`-h` collisions.** Some wrapped CLIs use `-h` for `--host`. Since moshcode
|
|
353
|
+
claims `-h` only before the tool/engine name (R1), this should be safe — but
|
|
354
|
+
it needs a test per tool, and `console --ttyd host:port` is a reminder that we
|
|
355
|
+
have host-shaped flags of our own.
|
|
356
|
+
- **Who owns `--help` inside `moshcode run`?** Stated as a constraint in UX
|
|
357
|
+
Notes, but a shebang script (`./deploy.mosh --help`) currently gets `--help` in
|
|
358
|
+
`argv` with no convention for what to do with it. Should moshscript ship a
|
|
359
|
+
`usage()` verb so scripts can answer for themselves?
|