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.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +580 -0
  3. package/bin/moshcode.mjs +674 -0
  4. package/bin/moshscript.mjs +29 -0
  5. package/examples/alive.mosh +6 -0
  6. package/examples/scripting-the-cli.mosh +21 -0
  7. package/examples/team-secrets.mosh +20 -0
  8. package/examples/templates/bun-caddy-sqlite/.env.example +14 -0
  9. package/examples/templates/bun-caddy-sqlite/Caddyfile +18 -0
  10. package/examples/templates/bun-caddy-sqlite/README.md +97 -0
  11. package/examples/templates/bun-caddy-sqlite/deploy/moshcode-dns.service +39 -0
  12. package/examples/templates/bun-caddy-sqlite/deploy/moshpit-service.service +38 -0
  13. package/examples/templates/bun-caddy-sqlite/package.json +15 -0
  14. package/examples/templates/bun-caddy-sqlite/src/db.ts +47 -0
  15. package/examples/templates/bun-caddy-sqlite/src/server.ts +44 -0
  16. package/examples/templates/bun-caddy-sqlite/template.json +10 -0
  17. package/examples/templates/caddy-proxy/Caddyfile +36 -0
  18. package/examples/templates/caddy-proxy/README.md +104 -0
  19. package/examples/templates/caddy-proxy/deploy/moshcode-dns.service +39 -0
  20. package/examples/templates/caddy-proxy/template.json +8 -0
  21. package/examples/templates/caddy-static/Caddyfile +16 -0
  22. package/examples/templates/caddy-static/README.md +90 -0
  23. package/examples/templates/caddy-static/deploy/moshcode-dns.service +39 -0
  24. package/examples/templates/caddy-static/site/index.html +11 -0
  25. package/examples/templates/caddy-static/template.json +8 -0
  26. package/install.sh +194 -0
  27. package/package.json +28 -0
  28. package/prd/0000-template.md +49 -0
  29. package/prd/0001-wrap-ugig-and-coinpay-clis.md +121 -0
  30. package/prd/0002-separate-agent-and-raw-engine-launches.md +113 -0
  31. package/prd/0003-cross-engine-mcp-and-skill-installation.md +165 -0
  32. package/prd/0004-moshscript-run-programmable-moshcode.md +344 -0
  33. package/prd/0005-hosted-moshpit-resolver.md +192 -0
  34. package/prd/0006-help.md +359 -0
  35. package/prd/0007-profullstack-site-init.md +1183 -0
  36. package/prd/README.md +26 -0
  37. package/src/ads.mjs +58 -0
  38. package/src/auth.mjs +193 -0
  39. package/src/cli-schema.mjs +533 -0
  40. package/src/cli.mjs +118 -0
  41. package/src/commands.mjs +259 -0
  42. package/src/completion.mjs +594 -0
  43. package/src/console.mjs +244 -0
  44. package/src/dns-system.mjs +404 -0
  45. package/src/dns.mjs +2872 -0
  46. package/src/doh-server.mjs +256 -0
  47. package/src/doh.mjs +218 -0
  48. package/src/engines.mjs +385 -0
  49. package/src/escalate.mjs +85 -0
  50. package/src/help.mjs +443 -0
  51. package/src/integrations.mjs +265 -0
  52. package/src/mcp-catalog.mjs +50 -0
  53. package/src/mcp.mjs +155 -0
  54. package/src/mirror.mjs +187 -0
  55. package/src/notify.mjs +86 -0
  56. package/src/open-url.mjs +34 -0
  57. package/src/parking-http.mjs +65 -0
  58. package/src/pins.mjs +190 -0
  59. package/src/pit-url.mjs +13 -0
  60. package/src/prd.mjs +341 -0
  61. package/src/pty.mjs +176 -0
  62. package/src/pwd.mjs +103 -0
  63. package/src/registry.mjs +37 -0
  64. package/src/release-install.mjs +191 -0
  65. package/src/runtime.mjs +161 -0
  66. package/src/selfupdate.mjs +215 -0
  67. package/src/serve.mjs +502 -0
  68. package/src/skills.mjs +93 -0
  69. package/src/tabs.mjs +144 -0
  70. package/src/templates.mjs +456 -0
  71. package/src/tools.mjs +231 -0
  72. package/src/trade.mjs +137 -0
  73. package/src/trust.mjs +712 -0
  74. package/src/tui.mjs +736 -0
  75. package/src/ui.mjs +49 -0
  76. package/src/uninstall.mjs +113 -0
  77. package/src/upgrade.mjs +217 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Profullstack, Inc. (dba moshcoding)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,580 @@
1
+ # moshcode 🤘
2
+
3
+ A metal wrapper CLI for agentic coding. moshcode doesn't reinvent the agent — it
4
+ **installs and drives** existing ones (opencode, Claude Code, codex) and adds a
5
+ tiny scripting toolkit (moshscript) on top. It also conducts adjacent native
6
+ workflow tools for finding work and getting paid.
7
+
8
+ ## Install
9
+
10
+ ```sh
11
+ curl -fsSL https://moshcoding.com/install.sh | sh
12
+ ```
13
+
14
+ Zero-dependency ESM — all it needs is Node.js 18+. Later: `… | sh -s -- update`
15
+ to upgrade, `… | sh -s -- remove` to uninstall.
16
+
17
+ ## Commands
18
+
19
+ `moshcode help <command>` drills into any of these — flags, examples and all.
20
+ `moshcode help --json` is the same thing for a machine.
21
+
22
+ This table is generated from the command table the CLI itself dispatches from
23
+ (`moshcode help --markdown`), so it cannot describe a verb that does not exist
24
+ or miss one that does. A test fails the build when it drifts.
25
+
26
+ <!-- COMMANDS:START -->
27
+ | command | group | what it does |
28
+ |---|---|---|
29
+ | `moshcode agents` | engines | list engines or launch one autonomously |
30
+ | `moshcode start` | engines | launch an engine with its native defaults |
31
+ | `moshcode install` | engines | install an engine or workflow tool |
32
+ | `moshcode uninstall` <br>`remove` | engines | take an engine or workflow tool off this machine |
33
+ | `moshcode upgrade` <br>`update` | engines | update moshcode, engines, or tools |
34
+ | `moshcode mcp` | extend | register and inspect MCP servers |
35
+ | `moshcode skill` <br>`skills` | extend | install and inspect agent skills |
36
+ | `moshcode prd` | script | publish or list product requirement documents |
37
+ | `moshcode login` | account | authenticate with app.moshcode.sh |
38
+ | `moshcode whoami` | account | show the logged-in account |
39
+ | `moshcode logout` | account | clear the logged-in account |
40
+ | `moshcode console` | account | serve or connect to the browser terminal |
41
+ | `moshcode dns` | hosting | resolve Moshpit names on this machine |
42
+ | `moshcode doh` | hosting | run the DNS-over-HTTPS resolver |
43
+ | `moshcode site` <br>`serve` | hosting | install web-server config for a Moshpit name |
44
+ | `moshcode template` <br>`templates` | hosting | scaffold a stack for a Moshpit-hosted service |
45
+ | `moshcode pwd` <br>`where` | system | show the current directory and git context |
46
+ | `moshcode engines` | engines | list engines and installation status |
47
+ | `moshcode tools` | tools | list workflow tools and installation status |
48
+ | `moshcode trade` | tools | look up markets and trade through Alpaca |
49
+ | `moshcode commands` | script | list built-in moshscript commands |
50
+ | `moshcode completion` | extend | print a shell completion script |
51
+ | `moshcode run` | script | run a moshscript |
52
+ | `moshcode help` <br>`--help` `-h` | system | show command help |
53
+ | `moshcode version` <br>`--version` `-v` | system | show the installed version |
54
+ <!-- COMMANDS:END -->
55
+
56
+ ## Engines
57
+
58
+ ```sh
59
+ moshcode engines # list installable engines
60
+ moshcode engines --json # machine-readable install status for automation
61
+ moshcode install opencode # install opencode (curl … | bash)
62
+ moshcode install privacycode # curl -fsSL https://getprivacycode.com/install | sh
63
+ moshcode install claude # npm i -g @anthropic-ai/claude-code
64
+ moshcode install codex # npm i -g @openai/codex
65
+ moshcode install kimi # curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash
66
+ moshcode install qwen # npm i -g @qwen-code/qwen-code
67
+ moshcode install deepseek # npm i -g @serjm/deepseek-code
68
+ ```
69
+
70
+ ### Autonomous agents versus raw starts
71
+
72
+ `agents` opens the engine's native **agent view** when it has one, so you land on
73
+ your agent list. Engines without an agents view instead start an autonomous
74
+ session by injecting the engine's native bypass or auto-approval mode. Either way,
75
+ use this only in an isolated container, VM, or workspace you trust:
76
+
77
+ ```sh
78
+ moshcode agents claude # claude agents --dangerously-skip-permissions (agent view)
79
+ moshcode agents opencode # opencode agent list (agent view)
80
+ moshcode agents privacycode # privacycode agent list (agent view)
81
+ moshcode agents codex # codex --dangerously-bypass-approvals-and-sandbox (autonomous)
82
+ moshcode agents gemini # gemini --approval-mode=yolo (autonomous)
83
+ moshcode agents kimi # kimi --yolo (autonomous)
84
+ moshcode agents qwen # qwen --approval-mode=yolo (autonomous)
85
+ moshcode agents deepseek # deepseek-code --turbo (autonomous)
86
+ moshcode agents aider # aider --yes-always (autonomous)
87
+ ```
88
+
89
+ `start` is the explicit raw path. It injects nothing, so the native engine keeps
90
+ its normal permission model and receives only your arguments:
91
+
92
+ ```sh
93
+ moshcode start claude
94
+ moshcode start codex --sandbox workspace-write
95
+ ```
96
+
97
+ Bare engine commands remain raw for backward compatibility, so `moshcode claude`
98
+ is shorthand for `moshcode start claude`. In the TUI, use `/agents <engine>` for
99
+ autonomous mode or `/start <engine>` for raw mode. Running `moshcode agents` or
100
+ `/agents` without an engine still lists engines and their install status.
101
+
102
+ ### Parallel pit tabs
103
+
104
+ At the mosh prompt, `/new` opens and switches to another independent moshcode
105
+ tab. Run `/agents <engine>` in each tab and switch between them with tmux's
106
+ `Ctrl-b n`, `Ctrl-b p`, or `Ctrl-b <number>` keys. If moshcode is already inside
107
+ tmux, `/new` adds a window to that session and respects its configured window
108
+ keys. Otherwise the first `/new` opens an isolated two-tab workspace with those
109
+ default keys and its tab bar at the bottom.
110
+
111
+ Each tab is a separate moshcode process and provider CLIs still receive an
112
+ ordinary inherited terminal. Moshcode does not intercept or reinterpret their
113
+ input, output, full-screen UI, or provider-specific shortcuts. The feature
114
+ requires `tmux`; without it `/new` reports that requirement and leaves the
115
+ current pit untouched.
116
+
117
+ The modes are not identical across providers. In particular, OpenCode `--auto`
118
+ auto-approves permission requests but continues to enforce explicit deny rules.
119
+
120
+ ## Workflow tools: UGig, CoinPay, and the cloud CLIs
121
+
122
+ These remain independent native CLIs with their own authentication,
123
+ configuration, command trees, output formats, and release cycles. MoshCode
124
+ installs them and passes control through without reimplementing their APIs.
125
+
126
+ The primary development toolchain runs through `moshcode` as a
127
+ [dev.profullstack.com](https://dev.profullstack.com/) user.
128
+
129
+ ```sh
130
+ moshcode tools # list tools and native install status
131
+ moshcode tools --json # machine-readable install status for automation
132
+ moshcode install ugig # runs the vendor's official install script
133
+ moshcode install coinpay # same — each tool owns its installer
134
+
135
+ moshcode ugig --json gigs list # arguments/output go straight to ugig
136
+ moshcode coinpay wallet balance # arguments/output go straight to coinpay
137
+ ```
138
+
139
+ ### Cloud + infra CLIs
140
+
141
+ ```sh
142
+ moshcode install railway # npm i -g @railway/cli
143
+ moshcode install gh # GitHub release binary → ~/.local/bin
144
+ moshcode install supabase # GitHub release binary (no global npm package exists)
145
+ moshcode install doppler # official script, installed user-local (needs gpgv)
146
+ moshcode install doctl # GitHub release binary → ~/.local/bin
147
+ moshcode install turso # official script → ~/.turso (new shell to pick up PATH)
148
+ moshcode install tailscale # official script; system daemon, so it needs root
149
+
150
+ moshcode gh pr list # straight through to the native CLI
151
+ moshcode railway up
152
+ moshcode doctl compute droplet list
153
+ ```
154
+
155
+ `gh`, `supabase`, and `doctl` publish no cross-platform install script, so
156
+ MoshCode resolves the latest GitHub release and drops the binary in
157
+ `$MOSHCODE_BIN` (default `~/.local/bin`) — no sudo, no package manager. Set
158
+ `MOSHCODE_BIN` to install elsewhere.
159
+
160
+ `tailscale` is the exception: it is a system daemon, so its official installer
161
+ goes through your distro's package manager and will ask for sudo (on macOS it
162
+ delegates to the App Store).
163
+
164
+ Top-level passthrough preserves stdin, stdout, stderr, environment variables,
165
+ the current directory, and the native exit result. That keeps JSON pipelines
166
+ usable:
167
+
168
+ ```sh
169
+ moshcode ugig --json gigs list | jq .
170
+ ```
171
+
172
+ Run `moshcode ugig --help` or `moshcode coinpay --help` for each tool's current
173
+ native setup and authentication commands. CoinPay currently requires Node.js
174
+ 20+, while MoshCode itself remains compatible with Node.js 18+.
175
+
176
+ In the TUI, use `/tools`, `/ugig [args…]`, or `/coinpay [args…]`. The native CLI
177
+ owns the terminal until it exits, then MoshCode returns to the pit.
178
+
179
+ ### Alpaca trading
180
+
181
+ Alpaca is a workflow tool, not a coding engine. Install its official Go CLI,
182
+ use `alpaca` for exact native passthrough, or use `trade` for the shorter market
183
+ and order vocabulary:
184
+
185
+ ```sh
186
+ moshcode install alpaca # go install github.com/alpacahq/cli/cmd/alpaca@latest
187
+ moshcode trade login # Alpaca profile login; paper trading is the default
188
+ moshcode trade ticker AAPL # asset get --symbol-or-asset-id AAPL
189
+ moshcode trade quote AAPL # latest quote
190
+ moshcode trade analysis AAPL # quote/trade/bar snapshot for analysis
191
+ moshcode trade watch # list watchlists
192
+ moshcode trade positions # list open positions
193
+ moshcode trade orders # list open orders
194
+ ```
195
+
196
+ `buy` and `sell` are safe previews unless `--submit` is explicit. Other Alpaca
197
+ order flags pass through, including limit prices and its separate live-trading
198
+ opt-in:
199
+
200
+ ```sh
201
+ moshcode trade buy AAPL 1 # adds --type market --dry-run
202
+ moshcode trade buy AAPL 1 --type limit --limit-price 185
203
+ moshcode trade buy AAPL --notional 100 # preview a $100 market buy
204
+ moshcode trade buy AAPL 1 --submit # places the paper order
205
+ moshcode trade raw data news --symbol AAPL # any native Alpaca command
206
+ moshcode alpaca order submit --help # exact native passthrough
207
+ ```
208
+
209
+ The same facade is `/trade …` in the pit and `trade(…)` in moshscript.
210
+ Alpaca's CLI has no confirmation prompts; `--submit` intentionally removes
211
+ MoshCode's preview guard. Live trading additionally requires Alpaca's `--live`
212
+ opt-in or corresponding environment setting.
213
+
214
+ ## Browser terminal (`moshcode console`)
215
+
216
+ A real terminal in the browser — arrow keys, history, full-screen TUIs — because
217
+ the thing on the other end is a real pty, not a log view. moshcode does not
218
+ implement the terminal: [ttyd](https://github.com/tsl0922/ttyd) does, and
219
+ moshcode puts an authenticating proxy in front of it so your `moshcode login` is
220
+ the way in.
221
+
222
+ Two processes on the box you want a shell on:
223
+
224
+ ```sh
225
+ # 1. ttyd — bound to loopback ONLY. It must never be reachable directly.
226
+ ttyd -i 127.0.0.1 -p 7681 -W login
227
+
228
+ # 2. the gateway — verifies moshcode tokens, then proxies to ttyd
229
+ moshcode console serve --port 7682 --ttyd 127.0.0.1:7681
230
+ ```
231
+
232
+ Then, from any machine where you have run `moshcode login`:
233
+
234
+ ```sh
235
+ moshcode console --url https://dev.example.com/ # prints an authenticated URL
236
+ ```
237
+
238
+ The token is verified once against `app.moshcode.sh/api/me`, swapped for a
239
+ short-lived HMAC cookie, and stripped from the URL by the redirect, so it does
240
+ not sit in browser history or travel with every request. The websocket carrying
241
+ the terminal is authenticated too — an unauthenticated upgrade is refused before
242
+ it reaches ttyd.
243
+
244
+ **This is a shell on the internet.** Treat it accordingly:
245
+
246
+ - Keep ttyd on `127.0.0.1`. The gateway is the only thing that should reach it.
247
+ - `--bind` defaults to `127.0.0.1`. Put the gateway on a **tailnet address**
248
+ (`moshcode install tailscale`) or behind a reverse proxy with TLS. Binding
249
+ `0.0.0.0` publishes a login prompt to the whole internet, and moshcode warns
250
+ when you do it.
251
+ - The gateway's signing secret is per-process, so restarting it logs everyone out.
252
+
253
+ ## MCP and Agent Skills
254
+
255
+ See which installed engines can handle MCP servers or Agent Skills. Add
256
+ `--json` when another tool needs the capability matrix:
257
+
258
+ ```sh
259
+ moshcode mcp list --json
260
+ moshcode skill list --json
261
+ ```
262
+
263
+ Each row reports `installed` and `supported` separately, so an installed engine
264
+ without that integration primitive remains visible rather than looking absent.
265
+
266
+ ### Known MCP servers
267
+
268
+ Some MCP servers are worth remembering by name rather than by npx invocation:
269
+
270
+ ```sh
271
+ moshcode mcp catalog # what we know how to run
272
+ moshcode mcp add porkbun # expands to: npx -y @porkbunllc/mcp-server
273
+ ```
274
+
275
+ That registers it across every engine that supports MCP (claude, gemini, codex,
276
+ opencode, privacycode) in one go. Kimi is skipped with a reason: it runs MCP
277
+ servers but has no command to register one from a script — add those in-session
278
+ with its own `/mcp-config`, or in `~/.kimi-code/mcp.json`.
279
+
280
+ The catalog is a convenience, never a gate — an explicit command always wins, so
281
+ `moshcode mcp add porkbun -- node ./my-fork.js` runs your fork.
282
+
283
+ **Credentials are named, not registered.** `porkbun` needs `PORKBUN_API_KEY` and
284
+ `PORKBUN_SECRET_API_KEY`; moshcode prints which are missing rather than copying
285
+ them into five engines' config files, which would be five places to leak them
286
+ from and five to rotate. Porkbun's API access is off by default and enabled
287
+ per-domain — and its documentation tools work with no keys at all, which is a
288
+ sensible way to try the server before trusting it with DNS writes.
289
+
290
+ ## Upgrade everything
291
+
292
+ ```sh
293
+ moshcode upgrade # moshcode + every installed engine and tool
294
+ moshcode upgrade claude # just one engine (name any; alias ok)
295
+ moshcode upgrade ugig # just one workflow tool
296
+ moshcode upgrade tools # all installed workflow tools, no self/engines
297
+ moshcode upgrade self # just moshcode itself
298
+ ```
299
+
300
+ Each target is updated with its own native updater when it has one (e.g.
301
+ `opencode upgrade`, `aider --upgrade`) and re-run through its installer
302
+ otherwise — MoshCode never vendors it. In the TUI: `/upgrade [name…]`.
303
+
304
+ ## Hosting at a Moshpit name (`moshcode template`)
305
+
306
+ Claim `foo.whatever` in [the Pit](https://pit.moshcode.sh/pit), then scaffold
307
+ something to put behind it:
308
+
309
+ ```sh
310
+ moshcode template list # what there is
311
+ moshcode template list --json # machine-readable template metadata
312
+ moshcode template install bun-caddy-sqlite # into the current directory
313
+ moshcode template install caddy-static --into /srv/site
314
+ moshcode template install owner/repo # or a git URL, or a .tar.gz
315
+ moshcode template install caddy-static --dry-run # preview every file first
316
+ ```
317
+
318
+ | template | what you get |
319
+ |---|---|
320
+ | `bun-caddy-sqlite` | Bun service + Caddy + SQLite — a local file in dev, Turso in prod, same client |
321
+ | `caddy-static` | Caddy and a directory of files. No runtime, nothing to keep alive. |
322
+
323
+ Each writes a Caddyfile, systemd units, and a README. **Nothing in a template is
324
+ executed on install** — including the bundled ones. `install <url>` takes a
325
+ stranger's URL, so the files are copied and what to run is yours to decide.
326
+ `--dry-run` labels every file as `create` or `overwrite` and leaves the target
327
+ directory unchanged; combine it with `--force` to preview an overwrite plan.
328
+
329
+ The one fact that catches everyone: **the machine serving the name never
330
+ resolves it, and every machine visiting it must.** Serving is a `Host` header
331
+ match and nothing more; visitors need `sudo moshcode dns enable` or the name
332
+ resolves to nothing.
333
+
334
+ Use JSON when a script needs to distinguish a live, parked, invalid, or
335
+ temporarily unreachable name without parsing terminal text:
336
+
337
+ ```sh
338
+ moshcode dns resolve foo.whatever --json
339
+ ```
340
+
341
+ A name points at an **IPv6 address** (bare — no scheme, brackets or port) or a
342
+ hostname. IPv4 literals are refused: an A record on a small host is usually
343
+ leased or NATed, and a name pointed at one goes stale silently.
344
+
345
+ Full walkthrough, including the layer-by-layer way to debug it and the limits
346
+ worth knowing before you build:
347
+ **[docs/hosting-a-moshpit-name.md](docs/hosting-a-moshpit-name.md)**.
348
+
349
+ ## Shell completion
350
+
351
+ MoshCode can print context-aware completion scripts for its commands, engines,
352
+ workflow tools, options, and file arguments. Load the one for your current
353
+ shell:
354
+
355
+ ```sh
356
+ # Bash (~/.bashrc)
357
+ source <(moshcode completion bash)
358
+
359
+ # Zsh (~/.zshrc, after any existing compinit/Oh My Zsh setup)
360
+ source <(moshcode completion zsh)
361
+
362
+ # Fish (~/.config/fish/config.fish)
363
+ moshcode completion fish | source
364
+
365
+ # PowerShell (add to $PROFILE for future sessions)
366
+ moshcode completion powershell | Out-String | Invoke-Expression
367
+ ```
368
+
369
+ Put the matching line in your shell profile to enable it in future sessions.
370
+
371
+ ## PRD — plan before you mosh
372
+
373
+ Write a product requirements doc *first*, then let your coding agents build to it.
374
+ `moshcode prd` publishes PRDs per [OpenPRD](https://github.com/profullstack/logicsrc/blob/master/docs/openprd.md) —
375
+ a **DIP-style** standard: a numbered, committed proposal collection in your repo
376
+ (like a BIP/EIP process), one file per decision.
377
+
378
+ ```sh
379
+ moshcode prd "parked-domain service expansion" # publish the next numbered PRD, then hand it to an engine
380
+ moshcode prd # list existing PRDs
381
+ moshcode prd list --json # machine-readable listing; writes nothing
382
+ ```
383
+
384
+ `moshcode prd <idea>` bootstraps `prd/` on first use (a `README.md` index +
385
+ `0000-template.md`), assigns the next four-digit number, writes
386
+ `prd/NNNN-slug.md` (status `Draft`), and hands it to a coding engine (Claude Code
387
+ by default) to author. PRDs are **committed** to the repo — they carry a lifecycle
388
+ (Draft → Review → Accepted → Final) in their front-matter.
389
+
390
+ ```txt
391
+ prd/
392
+ README.md # index of PRDs
393
+ 0000-template.md # the OpenPRD template
394
+ 0001-parked-domain-expansion.md
395
+ ```
396
+
397
+ In the TUI shell it's `/prd [idea]`.
398
+
399
+ ## moshscript
400
+
401
+ A metal scripting toolkit — **secretly all JS is legal**. The simple surface
402
+ stays dead-simple, but a `.mosh` file is real JavaScript under the hood with the
403
+ full moshcode command vocabulary injected as globals:
404
+
405
+ ```js
406
+ // alive.mosh — the starter script (unchanged, still works)
407
+ while (alive) {
408
+ code();
409
+ mosh();
410
+ notify();
411
+ repeat();
412
+ } // no bugs, only features
413
+ ```
414
+
415
+ The secret that it's all JS — no new syntax to learn:
416
+
417
+ ```js
418
+ // deploy-agents.mosh — real work, still reads like the toy
419
+ const engines = ["claude", "codex"];
420
+ for (const e of engines) {
421
+ install(e); // → moshcode install <e>
422
+ }
423
+ mcp("install", "https://mcp.sentry.dev/mcp"); // fan out across engines
424
+ say(`ready to mosh with ${engines.length} engines`);
425
+ agents("claude"); // drop into an autonomous session
426
+ ```
427
+
428
+ ### Run
429
+
430
+ ```sh
431
+ moshcode run examples/alive.mosh # run a script
432
+ moshcode run deploy.mosh --dry-run # narrate without executing
433
+ moshcode run alive.mosh --max 5 # bound the while loop (default 3)
434
+ moshcode run deploy.mosh staging --fast # extra args reach the script as argv
435
+ moshcode run deploy.mosh -- --max 5 # -- preserves option-like script args
436
+ moshcode run - < script.mosh # pipe/paste from stdin
437
+ moshcode commands # list the full vocabulary
438
+ moshcode commands --json # machine-readable command metadata
439
+ ```
440
+
441
+ No install/build step — it's plain ESM. `node bin/moshcode.mjs …` works too.
442
+
443
+ ### Shebang — self-running scripts
444
+
445
+ `.mosh` files support shebang lines, so `chmod +x` makes them run like shell
446
+ scripts. The `moshscript` executable is installed alongside `moshcode`:
447
+
448
+ ```js
449
+ #!/usr/bin/env moshscript
450
+ // deploy.mosh — chmod +x it and run it like any shell script
451
+ install("claude");
452
+ agents("claude");
453
+ ```
454
+
455
+ ```sh
456
+ chmod +x deploy.mosh
457
+ ./deploy.mosh # shebang → moshscript → moshcode run
458
+ ./deploy.mosh --dry-run staging # args after the file reach the script
459
+ ```
460
+
461
+ ### Commands
462
+
463
+ **Local verbs** (moshscript-only, in-process):
464
+
465
+ | verb | description |
466
+ |---|---|
467
+ | `code()` | compile features (no bugs) |
468
+ | `mosh()` | open the pit + blast the moshcoding playlist |
469
+ | `notify(msg)` | fire-and-forget ping + approval link on moshcode.sh |
470
+ | `ask(prompt)` | blocking gate — waits for human reply at moshcode.sh |
471
+ | `say("…")` | print a line |
472
+ | `sleep(ms)` | pause for N milliseconds (blocking) |
473
+ | `shell(cmd)` | run a shell command (blocking, `$SHELL -c`); returns `{ ok, code }` |
474
+ | `stop()` | end the loop (`alive = false`) |
475
+ | `repeat()` | back to the top of the loop |
476
+
477
+ **CLI verbs** (each shells out to `moshcode <name> ...args`):
478
+
479
+ | verb | description |
480
+ |---|---|
481
+ | `agents(engine)` | launch an autonomous agent session |
482
+ | `start(engine)` | raw-launch an engine |
483
+ | `install(target)` | install an engine or workflow tool |
484
+ | `upgrade(targets…)` | upgrade moshcode, engines, and tools |
485
+ | `mcp(args…)` | register/fan out an MCP server |
486
+ | `skill(args…)` | install a skill across engines |
487
+ | `prd(idea)` | publish/author an OpenPRD doc |
488
+ | `ugig(args…)` | drive the ugig workflow CLI |
489
+ | `coinpay(args…)` | drive the coinpay workflow CLI |
490
+ | `c0mpute(args…)` | drive the c0mpute workflow CLI |
491
+ | `secrets(args…)` | drive the logicsrc secrets CLI |
492
+ | `railway(args…)` | drive the Railway CLI |
493
+ | `gh(args…)` | drive the GitHub CLI |
494
+ | `supabase(args…)` | drive the Supabase CLI |
495
+ | `doppler(args…)` | drive the Doppler CLI |
496
+ | `doctl(args…)` | drive the DigitalOcean CLI |
497
+ | `turso(args…)` | drive the Turso CLI |
498
+ | `tailscale(args…)` | drive the Tailscale CLI |
499
+ | `pwd()` | print the current repo/location |
500
+ | `run(file)` | run another .mosh file (include/compose) |
501
+
502
+ **Specials** (injected globals, not commands):
503
+
504
+ | name | description |
505
+ |---|---|
506
+ | `alive` | `true` while the loop may continue; iterations bounded by `--max` |
507
+ | `argv` | positional args passed after the script file |
508
+ | `env` | `process.env` — parameterize scripts from the environment |
509
+
510
+ ### Human-in-the-loop
511
+
512
+ - `notify(msg)` — fire-and-forget. Pings the operator across configured channels
513
+ and surfaces an approval link at `app.moshcode.sh/approve/:id`. Returns `{ id, url }`.
514
+ - `ask(prompt)` — blocking gate. Same ping + link, then **blocks** until the
515
+ operator opens the link, reads the context, types instructions, and submits.
516
+ Resolves with their text (or `null` on timeout). Use with `await`:
517
+
518
+ ```js
519
+ const task = await ask("what should I work on next?");
520
+ say(`got it: ${task}`);
521
+ ```
522
+
523
+ ### Error handling
524
+
525
+ CLI verbs and `shell()` return `{ ok, code }` instead of throwing on non-zero
526
+ exits, so scripts can branch on outcomes without `try/catch`:
527
+
528
+ ```js
529
+ const r = install("claude");
530
+ if (!r.ok) {
531
+ say(`install failed (exit ${r.code}), trying fallback…`);
532
+ install("codex");
533
+ }
534
+
535
+ const test = shell("npm test");
536
+ if (!test.ok) notify("tests failed!");
537
+ ```
538
+
539
+ Only truly fatal errors (e.g. `moshcode` binary not found) throw. This keeps
540
+ `while (alive)` loops resilient — a single failing verb doesn't crash the script.
541
+
542
+ ### Dry run
543
+
544
+ `--dry-run` narrates every action without executing it — no engine spawns, no
545
+ installs, no network POSTs, no PRD writes:
546
+
547
+ ```
548
+ $ moshcode run deploy.mosh --dry-run
549
+ 🎸 moshcode — running moshscript (dry run)
550
+
551
+ ▶ install(claude) → would run: moshcode install claude
552
+ ▶ mcp(install, https://mcp.sentry.dev/mcp) → would run: moshcode mcp install …
553
+ 💬 ready to mosh with 2 engines
554
+ ▶ agents(claude) → would run: moshcode agents claude
555
+
556
+ ✓ 0 loop(s) — no bugs, only features. 🤘
557
+ ```
558
+
559
+ ### Add your own commands
560
+
561
+ The vocabulary is open for extension via the registry:
562
+
563
+ ```js
564
+ import { moshVocabulary } from "moshcode/src/commands.mjs";
565
+ import { runScript } from "moshcode/src/runtime.mjs";
566
+
567
+ const commands = moshVocabulary();
568
+ commands.register({ name: "deploy", summary: "ship it", run: (ctx) => ctx.out("shipping…") });
569
+ await runScript(src, { commands });
570
+ ```
571
+
572
+ ## Env
573
+
574
+ | var | default | purpose |
575
+ |---|---|---|
576
+ | `MOSHCODE_API` | `https://moshcoding.com` | web-notifications endpoint host |
577
+ | `MOSHCODE_SITE` | `https://app.moshcode.sh` | approval URL base |
578
+ | `MOSHCODE_WEBHOOK_URL` | — | optional extra webhook for `notify()` |
579
+ | `MOSHCODE_WEBHOOK_SECRET` | — | signs notify() posts |
580
+ | `MOSHCODE_PLAYLIST` | — | what `mosh()` blasts in the browser |