Repository navigation
Add a foreground freebuff update command - #1554
yablokolabs wants to merge 2 commits into
Conversation
Users could only pick up a new release by waiting for the launcher's background check or restarting the CLI. The npm wrapper already knows how to fetch, verify and install a release, so `freebuff update` now runs that same install in the foreground and reports the result. A binary started without the wrapper says so and points at npm instead of crashing on an unknown command. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
|
Good work here. The core idea — reusing A few things worth double-checking before this gets ported:
Overall this is in-scope, correct in the common case, and tested to a standard the maintainers will appreciate. Flag the argv-parsing edge case above when it's ported. |
The launcher and the binary's command check are shared with codebuff and codecane, where the first positional argument is the prompt. Gating on a wrapper config flag keeps `codebuff update the readme` from installing a release and dropping the prompt. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
|
Thanks @codebuff-team — went through all three, plus one thing the review only hinted at. Value-taking flags.
Concurrent staged update. Already safe, so no comment needed. What did need fixing: the command wasn't scoped to freebuff. Both Tests: |
What
Adds
freebuff update, which installs the latest release right away instead of waiting for the launcher's background check or the exit-time install a deferred update uses.Why
Today a new release only lands after a restart: the npm wrapper stages it while the session runs and moves it into place on exit. Users who leave the CLI open (or never see the background check finish) have no way to ask for the update. The wrapper already implements fetch → sha256 verify → extract → atomic install, so the command reuses that path rather than adding a second one.
How
cli/release-core/launcher.jsisUpdateCommand()reads argv and finds the first positional argument, skipping flags and--cwd's value, so a directory namedupdateis not mistaken for the command.runUpdateCommand()prints the installed version, resolveslatestfrom the npm registry, exits 0 with "already up to date" when nothing is newer, and otherwise runs the existingstageBinary()+installStagedBinary()with the registry's checksums. Failures print throughprintDownloadFailure()and exit 1, leaving the installed binary untouched.main()dispatches to it before the binary is spawned, so no running process holds the files being replaced.freebuff/cli/release/index.jssets the newsupportsUpdateCommandwrapper flag.isUpdateCommand()returns false for every wrapper that doesn't set it (see Scoping below).cli/src/cli-args.tsacceptsupdateas a command, so the freebuff binary no longer rejects it.cli/src/index.tsxexplains the case where the binary was started without the npm wrapper: for freebuff it points atnpm install -g freebuff@latestinstead of failing on an unknown command.README.mddocuments the command.Scoping
Only the freebuff binary defines an
updatecommand. The launcher and the binary's command check are both shared with the codebuff and codecane wrappers, where the first positional argument is a prompt:codebuff update the readmeparses as{ command: 'update', initialPrompt: 'update the readme' }. Intercepting it there would install a release and drop what the user typed, so the command is gated behindsupportsUpdateCommand(set only by the freebuff wrapper) in the launcher andIS_FREEBUFFinindex.tsx.Tests
bun test cli/src/__tests__/release/update-command.test.ts(8 passing) covers command detection (including--cwd update,--, and a codebuff config that must not detect it), the up-to-date no-op, a full download/verify/install against a local release server, unknown latest version, checksum mismatch (fails closed), and a first install with no cached binary.cli-args.test.tscovers the new command, andwrapper-safety.test.tspins the freebuff wrapper config alongside the codebuff and codecane ones that must not set the flag.