Skip to content

0.12.0: companions — timer and billing install with the set - #26

Merged
ralyodio merged 1 commit into
masterfrom
worktree-cli-tools-companions
Aug 29, 2026
Merged

0.12.0: companions — timer and billing install with the set#26
ralyodio merged 1 commit into
masterfrom
worktree-cli-tools-companions

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

moshcode install cli-tools now also puts @profullstack/timer and @profullstack/billing on the box. That is the whole point: one install, and /timer and /billing work in the pit — moshcode hands both straight to these CLIs once they exist (moshcode#439).

What a companion is

A command this set ships but does not implement: a published npm package that brings its own binary.

$ cli-tools companions
Published separately, installed from npm:

* timer            Track time against projects, for people and for agents
                   @profullstack/timer
* billing          Clients, rates and invoices from the hours the timer tracked
                   @profullstack/billing

They are deliberately not bin/*.ts like everything else. They run on Windows, which this install cannot — it is symlinks into a git checkout executed through an npx tsx shebang — and they are useful with no checkout at all: under any agentic CLI, from a Dockerfile, on a box that has never heard of this repository. Vendoring them to make one list tidier would cost them both of those. So cli-tools is their front door, not their implementation.

Where they hook in

cli-tools companions [--install [--force]] new verb
cli-tools link installs the missing ones
cli-tools update reinstalls at @latest
cli-tools list a From npm: block
install.sh after linking, warns rather than dying
cli-tools unlink leaves them installed

update names @latest explicitly because a bare npm install -g <pkg> leaves an already-satisfied version in place — without the tag, update would silently never move them. unlink leaves them because they work without this checkout, and npm rm -g is not a decision to make on somebody's behalf. install.sh runs them through the checkout's own dispatcher rather than $PREFIX/cli-tools, so it still works on a box where another checkout owns that name. CLI_TOOLS_NO_COMPANIONS=1 skips the lot.

Two things the shape refuses to get wrong

An already-installed companion is left alone unless --force. It may be a newer version, a local build, or a fork somebody is testing — the same surprise link refuses for symlinks.

npm exiting 0 is not success if the binary is still not on PATH. npm will happily install into a prefix nobody can reach; reporting "installed" there sends you to a command you cannot run. That is the gap turso and gradient have in moshcode.

A stale allowlist, caught twice

KNOWN_VERBS is now exported and held against USAGE by a test. The old inline list going stale has a quiet symptom — a verb documented in the help falls through to the command passthrough and answers unknown command — and it had already happened to help once. It happened again to companions while writing this, which is why the test exists. It also caught that help and where are dispatched but missing from the synopsis, so it reads the Commands: block too.

Verified

Installed for real on this box, not mocked:

$ cli-tools companions --install
timer: installed @profullstack/timer
billing: installed @profullstack/billing
$ timer --version && billing --version
0.2.0
0.2.0
$ moshcode timer status      # now the standalone CLI, via moshcode#439
no clock running

pnpm test 455 passing, pnpm typecheck clean, sh -n install.sh clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KVUZsx4WBZK5rnJJFGgwF5

`moshcode install cli-tools` now also puts @profullstack/timer and
@profullstack/billing on the box, which is the whole point: one install, and
/timer and /billing work in the pit (moshcode hands both straight to these CLIs
once they exist).

A companion is a command this set ships but does not implement — a published
npm package with its own binary. They are deliberately not bin/*.ts like
everything else: they run on Windows, which this install cannot (symlinks into
a git checkout executed through an `npx tsx` shebang), and they are useful with
no checkout at all, under any agentic CLI. Vendoring them to make one list
tidier would cost them both of those. So this is their front door, not their
implementation.

  cli-tools companions [--install [--force]]

`link` installs the missing ones, `update` reinstalls at @latest — a bare
`npm install -g <pkg>` leaves an already-satisfied version in place, so without
the tag update would silently never move them. `unlink` leaves them installed:
they work without this checkout, and `npm rm -g` is not a decision to make on
somebody's behalf. install.sh runs them through the checkout's own dispatcher
rather than $PREFIX/cli-tools, so it still works on a box where another
checkout owns that name, and warns rather than dying like the Stripe block.
CLI_TOOLS_NO_COMPANIONS=1 skips the lot.

Two things the shape refuses to get wrong. An already-installed companion is
left alone unless --force: it may be a newer version, a local build or a fork
somebody is testing, which is the same surprise `link` refuses for symlinks.
And npm exiting 0 is not reported as success when the binary is still not on
PATH — npm will happily install into a prefix nobody can reach, and saying
"installed" there sends you to a command you cannot run.

KNOWN_VERBS is now exported and held against USAGE by a test. The old inline
allowlist going stale has a quiet symptom — a verb documented in the help falls
through to the command passthrough and answers "unknown command" — and it had
already happened to `help` once. It happened again to `companions` while
writing this. The test also caught that `help` and `where` are dispatched but
missing from the synopsis, so it reads the Commands: block too.

455 tests.
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

13 finding(s)

HIGH/CRITICAL: 5 | MEDIUM: 1 | LOW: 7

Severity Rule Location
HIGH sh-remote-script-execution root-ubuntu.sh:134
HIGH sh-remote-script-execution root-ubuntu.sh:2597
HIGH sh-remote-script-execution root-ubuntu.sh:2601
HIGH sh-remote-script-execution root-ubuntu.sh:2654
HIGH sh-remote-script-execution root-ubuntu.sh:3683
MEDIUM redos-nested-quantifier src/domain-free.ts:56
LOW secret-generic-credential src/credentials.ts:36
LOW insecure-temp-file test/blog.test.ts:73
LOW insecure-temp-file test/blog.test.ts:74
LOW insecure-temp-file test/credentials.test.ts:43
LOW insecure-temp-file test/credentials.test.ts:44
LOW secret-generic-api-key test/credentials.test.ts:208
LOW secret-generic-credential test/shorten.test.ts:36

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit d232138 into master Aug 29, 2026
5 checks passed
@ralyodio
ralyodio deleted the worktree-cli-tools-companions branch August 29, 2026 07:30
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