Skip to content

Commit 1884abc

Browse files
ralyodioclaude
andcommitted
Merge branch 'main' into feat/proxy-loopback
Two textual conflicts in src/dns.mjs, both additive: main's --trust-all auto-trust and this branch's --proxy loopback mode touch the same deps block and the same onQuery handler. Kept both — the flags are independent, so proxy mode passes proxyAddress through while auto-trust still considers each name that resolved to something of ours. Also one conflict git could not see: main's template list --json test (#284) asserts an exact template list, and this branch adds caddy-proxy. Added it to the expectation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2 parents 9602efe + 029a64f commit 1884abc

45 files changed

Lines changed: 1828 additions & 55 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ or miss one that does. A test fails the build when it drifts.
4545
| `moshcode pwd` <br>`where` | system | show the current directory and git context |
4646
| `moshcode engines` | engines | list engines and installation status |
4747
| `moshcode tools` | tools | list workflow tools and installation status |
48+
| `moshcode trade` | tools | look up markets and trade through Alpaca |
4849
| `moshcode commands` | script | list built-in moshscript commands |
4950
| `moshcode completion` | extend | print a shell completion script |
5051
| `moshcode run` | script | run a moshscript |
@@ -61,6 +62,9 @@ moshcode install opencode # install opencode (curl … | bash)
6162
moshcode install privacycode # curl -fsSL https://getprivacycode.com/install | sh
6263
moshcode install claude # npm i -g @anthropic-ai/claude-code
6364
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
6468
```
6569

6670
### Autonomous agents versus raw starts
@@ -76,6 +80,9 @@ moshcode agents opencode # opencode agent list (agen
7680
moshcode agents privacycode # privacycode agent list (agent view)
7781
moshcode agents codex # codex --dangerously-bypass-approvals-and-sandbox (autonomous)
7882
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)
7986
moshcode agents aider # aider --yes-always (autonomous)
8087
```
8188

@@ -92,6 +99,21 @@ is shorthand for `moshcode start claude`. In the TUI, use `/agents <engine>` for
9299
autonomous mode or `/start <engine>` for raw mode. Running `moshcode agents` or
93100
`/agents` without an engine still lists engines and their install status.
94101

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+
95117
The modes are not identical across providers. In particular, OpenCode `--auto`
96118
auto-approves permission requests but continues to enforce explicit deny rules.
97119

@@ -154,6 +176,41 @@ native setup and authentication commands. CoinPay currently requires Node.js
154176
In the TUI, use `/tools`, `/ugig [args…]`, or `/coinpay [args…]`. The native CLI
155177
owns the terminal until it exits, then MoshCode returns to the pit.
156178

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+
157214
## Browser terminal (`moshcode console`)
158215

159216
A real terminal in the browser — arrow keys, history, full-screen TUIs — because
@@ -216,7 +273,9 @@ moshcode mcp add porkbun # expands to: npx -y @porkbunllc/mcp-server
216273
```
217274

218275
That registers it across every engine that supports MCP (claude, gemini, codex,
219-
opencode, privacycode) in one go.
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`.
220279

221280
The catalog is a convenience, never a gate — an explicit command always wins, so
222281
`moshcode mcp add porkbun -- node ./my-fork.js` runs your fork.
@@ -249,6 +308,7 @@ something to put behind it:
249308

250309
```sh
251310
moshcode template list # what there is
311+
moshcode template list --json # machine-readable template metadata
252312
moshcode template install bun-caddy-sqlite # into the current directory
253313
moshcode template install caddy-static --into /srv/site
254314
moshcode template install owner/repo # or a git URL, or a .tar.gz

bin/moshcode.mjs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
runCmd,
1616
} from "../src/engines.mjs";
1717
import { TOOLS, toolList, toolStatus, resolveTool, openTool } from "../src/tools.mjs";
18+
import { tradeArgs, tradeUsage } from "../src/trade.mjs";
1819
import { runUpgrade } from "../src/upgrade.mjs";
1920
import { selfUpdateCommand } from "../src/selfupdate.mjs";
2021
import { describeUninstall, uninstallPlan } from "../src/uninstall.mjs";
@@ -317,6 +318,29 @@ async function main() {
317318
}
318319
return;
319320
}
321+
if (cmd === "trade") {
322+
const translated = tradeArgs(rest);
323+
if (translated.usage) {
324+
console.log(tradeUsage());
325+
return;
326+
}
327+
if (translated.error) {
328+
console.error(`${translated.error}\n\n${tradeUsage()}`);
329+
process.exitCode = 1;
330+
return;
331+
}
332+
const tool = TOOLS.alpaca;
333+
const r = await openTool(tool, translated.args);
334+
if (!r.ok) {
335+
console.error(r.error?.code === "ENOENT"
336+
? `alpaca isn't installed (\`${tool.bin}\`). run: moshcode install alpaca`
337+
: `launch failed: ${r.error?.message || r.error}`);
338+
process.exitCode = 1;
339+
return;
340+
}
341+
propagateExit(r.code, r.signal);
342+
return;
343+
}
320344
if (cmd === "console") {
321345
const code = await consoleCommand(rest);
322346
if (code) process.exitCode = code;
@@ -345,6 +369,7 @@ async function main() {
345369
const result = await runCmd(install.cmd, install.args);
346370
if (!result.ok) {
347371
console.error(`install failed: ${result.error?.message || result.error || "unknown error"}`);
372+
if (result.error?.code === "ENOENT" && entry.installHelp) console.error(entry.installHelp);
348373
process.exitCode = 1;
349374
return;
350375
}
@@ -417,7 +442,7 @@ async function main() {
417442
return results.filter((r) => !r.ok).length ? 1 : 0;
418443
},
419444
write: (path, body) => fsp.writeFile(path, body),
420-
runner: (cmd2, args2) => new Promise((res) => execFile(cmd2, args2, () => res({ ok: true }))),
445+
runner: (cmd2, args2) => new Promise((res) => execFile(cmd2, args2, (err) => res({ ok: !err }))),
421446
})) || 0;
422447
return;
423448
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "moshcode",
3-
"version": "0.19.1",
3+
"version": "0.22.1",
44
"type": "module",
55
"description": "moshcode — a metal wrapper for coding engines and native UGig/CoinPay workflow CLIs, with OpenPRD and moshscript",
66
"bin": {

src/cli-schema.mjs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,15 @@ export const CORE_CLI_COMMANDS = [
229229
group: "hosting",
230230
description: "scaffold a stack for a Moshpit-hosted service",
231231
synopsis: [
232-
["moshcode template list", "what there is"],
232+
["moshcode template list [--json]", "what there is"],
233233
["moshcode template install <name>", "write it here"],
234234
],
235+
flags: [
236+
["--into <dir>", "write somewhere other than the current directory", ""],
237+
["--force", "overwrite files that are already there", ""],
238+
["--dry-run", "show changes without writing anything", ""],
239+
["--json", "machine-readable template list", ""],
240+
],
235241
examples: [["moshcode template install bun-caddy-sqlite", ""]],
236242
seeAlso: ["site"],
237243
},
@@ -261,6 +267,21 @@ export const CORE_CLI_COMMANDS = [
261267
flags: [["--json", "machine-readable, and suppresses the trailing note", ""]],
262268
seeAlso: ["install"],
263269
},
270+
{
271+
name: "trade",
272+
group: "tools",
273+
description: "look up markets and trade through Alpaca",
274+
synopsis: [["moshcode trade <verb> [args…]", "paper trading is Alpaca's default"]],
275+
verbs: "TRADE_VERBS",
276+
examples: [
277+
["moshcode trade ticker AAPL", "asset lookup"],
278+
["moshcode trade analysis AAPL", "quote/trade/bar snapshot"],
279+
["moshcode trade buy AAPL 1", "preview a market order"],
280+
["moshcode trade buy AAPL 1 --submit", "place it"],
281+
],
282+
seeAlso: ["tools", "install"],
283+
note: "buy/sell inject --dry-run unless --submit is present. Alpaca defaults to paper trading; live trading requires its separate --live opt-in.",
284+
},
264285
{
265286
name: "commands",
266287
group: "script",
@@ -389,6 +410,35 @@ export const UPGRADE_TARGETS = [
389410
{ name: "tools", description: "update all installed workflow tools" },
390411
];
391412

413+
export const TRADE_VERBS = [
414+
{ name: "ticker", description: "look up an asset by ticker", synopsis: [["moshcode trade ticker <symbol> [flags…]", ""]] },
415+
{ name: "quote", description: "get the latest quote", synopsis: [["moshcode trade quote <symbol> [flags…]", ""]] },
416+
{ name: "analysis", description: "get an analysis-ready market snapshot", synopsis: [["moshcode trade analysis <symbol> [flags…]", ""]] },
417+
{
418+
name: "buy", description: "preview or submit a buy order",
419+
synopsis: [
420+
["moshcode trade buy <symbol> <qty> [alpaca flags…] [--submit]", "share quantity"],
421+
["moshcode trade buy <symbol> --notional <usd> [--submit]", "dollar amount"],
422+
],
423+
flags: [["--submit", "place the order instead of injecting --dry-run", "preview"]],
424+
},
425+
{
426+
name: "sell", description: "preview or submit a sell order",
427+
synopsis: [
428+
["moshcode trade sell <symbol> <qty> [alpaca flags…] [--submit]", "share quantity"],
429+
["moshcode trade sell <symbol> --notional <usd> [--submit]", "dollar amount"],
430+
],
431+
flags: [["--submit", "place the order instead of injecting --dry-run", "preview"]],
432+
},
433+
{ name: "watch", description: "manage watchlists", synopsis: [["moshcode trade watch [list|create|get|add|remove|delete] [args…]", ""]] },
434+
{ name: "positions", description: "list, inspect, or close positions", synopsis: [["moshcode trade positions [verb] [args…]", "default: list"]] },
435+
{ name: "orders", description: "list, inspect, replace, or cancel orders", synopsis: [["moshcode trade orders [verb] [args…]", "default: list"]] },
436+
{ name: "account", description: "show account details", synopsis: [["moshcode trade account [args…]", ""]] },
437+
{ name: "login", description: "authenticate an Alpaca profile", synopsis: [["moshcode trade login [alpaca profile flags…]", "paper by default"]] },
438+
{ name: "clock", description: "show market status and next open/close", synopsis: [["moshcode trade clock [args…]", ""]] },
439+
{ name: "raw", description: "invoke the native Alpaca command tree", synopsis: [["moshcode trade raw <alpaca args…>", ""]] },
440+
];
441+
392442
/**
393443
* `dns` sub-verbs.
394444
*
@@ -406,6 +456,7 @@ export const DNS_VERBS = [
406456
{ name: "service", description: "install or remove the background service" },
407457
{ name: "tlds", description: "list the endings claimed in the Pit" },
408458
{ name: "resolve", description: "what a name resolves to, and why" },
459+
{ name: "trust", description: "trust one name's certificate, after checking it against the registry pin" },
409460
];
410461

411462
/** Sub-verb tables, by the name a command's `verbs` field refers to. */
@@ -414,6 +465,7 @@ export const VERB_TABLES = {
414465
SKILL_VERBS,
415466
UPGRADE_TARGETS,
416467
DNS_VERBS,
468+
TRADE_VERBS,
417469
};
418470

419471
/**
@@ -430,12 +482,16 @@ export const VERB_TABLES = {
430482
* than a second, thinner copy that drifts.
431483
*/
432484
export const PIT_COMMANDS = [
485+
{ name: "new", pitOnly: true,
486+
description: "open and switch to another moshcode tab" },
433487
{ name: "agents", aliases: ["agent", "engines"], args: "[name]", cli: "agents",
434488
description: "list engines, or launch one autonomously" },
435489
{ name: "start", args: "<engine> [args…]", cli: "start",
436490
description: "raw launch; inject no engine arguments" },
437491
{ name: "tools", args: "[name] [args…]", cli: "tools",
438492
description: "list workflow tools, or run one" },
493+
{ name: "trade", args: "<verb> [args…]", cli: "trade",
494+
description: "look up markets and preview/place Alpaca orders" },
439495
{ name: "install", args: "<engine|tool>", cli: "install",
440496
description: "install an engine or workflow tool" },
441497
{ name: "upgrade", aliases: ["update"], args: "[name…]", cli: "upgrade",

src/commands.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ const COMMANDS = [
248248
cliVerb("doctl", "drive the DigitalOcean CLI (droplets, apps, databases)"),
249249
cliVerb("turso", "drive the Turso CLI (auth, databases, replicas)"),
250250
cliVerb("tailscale", "drive the Tailscale CLI (mesh VPN: up, status, ssh, serve)"),
251+
cliVerb("alpaca", "drive the native Alpaca trading CLI"),
252+
cliVerb("trade", "look up tickers, inspect markets, and preview/place Alpaca orders"),
251253
cliVerb("pwd", "print the current repo/location"),
252254
];
253255

0 commit comments

Comments
 (0)