Skip to content

install: wire a tool's pit aliases into installing it - #431

Merged
ralyodio merged 1 commit into
mainfrom
tool-aliases
Aug 19, 2026
Merged

install: wire a tool's pit aliases into installing it#431
ralyodio merged 1 commit into
mainfrom
tool-aliases

Conversation

@ralyodio

@ralyodio ralyodio commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

What

Installing a workflow tool now configures it. cli-tools ships seven commands behind one dispatcher, and none of them are reachable from the pit until the words that reach them exist — so /install sets those up:

mosh ▸ /install cli-tools          # or /tools install cli-tools
✓ cli-tools installed. 🤘
  ✓ /blog → blog-post
  ✓ /free → domainfree

/upgrade does the same, because an upgrade is where a tool gains commands. That is exactly how cli-tools' own generate-names shipped in their #11 and never reached anybody's prompt.

moshcode install <tool> from the CLI does it too, in plain text. /alias install <tool> | --all re-runs it on demand, for tools installed before this existed.

/tools install <name> also routes to the installer now, instead of answering unknown tool "install" — it's the obvious spelling right after /tools prints the roster.

How

  • A tool declares an aliases spec in TOOLS (cli-toolscli-tools aliases --json). Declared, not probedaliases --json guessed at every installed CLI would eventually hit one where those words mean something else.
  • readToolAliases captures and validates. Every failure (not installed, non-zero exit, not JSON, not an object) is a returned reason, never a throw. stdin is ignore so a tool that decides to ask a question can't hang the pit on an invisible prompt.
  • mergeAliases does the write. A name you bound yourself always wins — your /prs may carry --orgs flags a generic suggestion knows nothing about. Names colliding with a pit command/engine/tool are refused for the reason setAlias refuses them: built-ins resolve first, so such an alias would be dead on arrival. Capped at 64.
  • Quiet by construction, which is what makes it safe to hang off an install: a tool offering nothing (every engine, most tools) prints nothing and spawns nothing, and one that can't be asked stays silent rather than following a successful install with an error about a nicety.

Tests

20 in test/alias-install.test.mjs: parse/failure modes with an injected runner, the undeclared-tool path asserting nothing is executed on a guess, merge semantics (existing wins, reserved refused, unusable values refused, cap + drop), the post-install line builder including a real binary reached over PATH, /tools install routing, and six end-to-end pit runs.

Two pre-existing problems in test/tools.test.mjs that this surfaced, both fixed:

  • its fake shell is a spy that a tool's own shebang could re-enter and overwrite, so the assertion could read the wrong invocation;
  • its runner never isolated $HOME, so a successful install in the suite could write the aliases of whoever ran it.

Full suite green: 2324 tests, 0 fail.

🤖 Generated with Claude Code

Several tools in the roster ship a set of commands rather than one binary,
and propose short words for them at the pit prompt. Until now the only way
to get those words was to let the tool write ~/.moshcode/aliases.json
itself — a config it does not own, and the same objection that keeps
`railway setup agent` out of /install.

So the tool proposes and the pit disposes. A tool declares an `aliases`
spec in TOOLS; `/alias install <tool>` runs it, reads the JSON, and merges
it. Declared rather than probed: `aliases --json` guessed at every
installed CLI would eventually hit one where those words mean something
else.

A name the operator bound themselves always wins and is named in the
report rather than silently kept — theirs and the tool's suggestion are
both plausible, and the pit's own aliases carry flags (--orgs, --apply)
that a generic suggestion knows nothing about. Names that collide with a
pit command, engine, or tool are refused for the reason /alias set refuses
them: built-ins resolve first, so such an alias would be dead on arrival.

Its own verb rather than a step inside /install, because writing the
operator's aliases is a side effect an install command has no business
having — and a roster is worth adopting long after the day a tool was
installed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

3 finding(s) in the 6 file(s) this pull request changes.

MEDIUM: 3

Severity Rule Location
MEDIUM sql-string-concatenation src/cli-schema.mjs:161
MEDIUM sql-string-concatenation src/cli-schema.mjs:460
MEDIUM sql-string-concatenation src/cli-schema.mjs:586
52 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 5 | **MEDIUM**: 41 | **LOW**: 6

Not introduced by this pull request. The full set is in the Security tab.

Severity Rule Location
HIGH js-ssrf-outbound-request apps/pwa/public/sw.js:45
HIGH tls-verification-disabled apps/pwa/src/lib/moshpit-gateway.mjs:299
HIGH sh-remote-script-execution install.sh:79
HIGH sh-remote-script-execution install.sh:83
HIGH tls-verification-disabled src/dns.mjs:741
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:68
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:82
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:108
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:295
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:299
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:344
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:568
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:749
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:751
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:810
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:856
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:926
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1029
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1052
MEDIUM sql-template-interpolation apps/pwa/src/moshpit.mjs:1074

…and 32 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit 2b5752b into main Aug 19, 2026
6 checks passed
@ralyodio ralyodio changed the title alias: let the pit adopt the shortcuts a workflow tool offers install: wire a tool's pit aliases into installing it Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant