feat(cli): DX improvements — force reinstall, doctor --fix, actionable errors (1.8.0)#63
Merged
Conversation
- AddIO.rmDir? + getBricksDir? optional methods for dir purge - forcePurgeBrick helper: wipes corrupted pkg dir, removes from state, then re-installs — skips the "already installed" guard - addCommand/addManyCommand forward force flag - Tests: force-reinstall, no-already-installed message, rmDir invocation, bundle brick cascade (tools=0, deps>0) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
focus reinstall <X> [Y Z ...] — alias for remove + add --force that preserves the brick's enabled state. Useful for bulk recovery after `focus doctor` detects corrupted installs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When --fix is passed, doctor auto-remediates: - Corrupted installs (pkg dir missing, dist missing, invalid manifest, lock entry missing) → focus reinstall <name> - Missing declared dependencies → focus add <dep> Version drift is intentionally NOT auto-fixed (use focus upgrade). Prints actions taken and re-runs doctor at the end to show updated state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When loadBricks reports a failure with a 'Missing dependency "X"' message, enrich the stderr output with three actionable commands: focus add X # install the missing dep focus reinstall Y # if Y's install is corrupted focus doctor # full diagnostic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…doctor-fix to CLI - focus add [-f/--force] <name>: parse force flag, wire rmDir/getBricksDir - focus reinstall <name> [...]: new command wired through runReinstall - focus doctor [--fix]: parse --fix flag, re-run after fixes in text mode - HELP text updated with all new flags and commands - Bundle bricks verified: tools=[] + deps>0 cascades identically to normal bricks (resolveDeps is agnostic to tools count) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
samuelds
added a commit
that referenced
this pull request
Apr 28, 2026
* feat(cli): DX improvements — force reinstall, doctor --fix, actionable errors (1.8.0) (#63) * feat(cli): add --force flag to focus add - AddIO.rmDir? + getBricksDir? optional methods for dir purge - forcePurgeBrick helper: wipes corrupted pkg dir, removes from state, then re-installs — skips the "already installed" guard - addCommand/addManyCommand forward force flag - Tests: force-reinstall, no-already-installed message, rmDir invocation, bundle brick cascade (tools=0, deps>0) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): add focus reinstall command focus reinstall <X> [Y Z ...] — alias for remove + add --force that preserves the brick's enabled state. Useful for bulk recovery after `focus doctor` detects corrupted installs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): focus doctor --fix flag When --fix is passed, doctor auto-remediates: - Corrupted installs (pkg dir missing, dist missing, invalid manifest, lock entry missing) → focus reinstall <name> - Missing declared dependencies → focus add <dep> Version drift is intentionally NOT auto-fixed (use focus upgrade). Prints actions taken and re-runs doctor at the end to show updated state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): actionable error on Missing dependency at start time When loadBricks reports a failure with a 'Missing dependency "X"' message, enrich the stderr output with three actionable commands: focus add X # install the missing dep focus reinstall Y # if Y's install is corrupted focus doctor # full diagnostic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): cascade auto-deps for bundle bricks + wire reinstall/force/doctor-fix to CLI - focus add [-f/--force] <name>: parse force flag, wire rmDir/getBricksDir - focus reinstall <name> [...]: new command wired through runReinstall - focus doctor [--fix]: parse --fix flag, re-run after fixes in text mode - HELP text updated with all new flags and commands - Bundle bricks verified: tools=[] + deps>0 cascades identically to normal bricks (resolveDeps is agnostic to tools count) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(release): cli 1.8.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): test fix — move enrichStartError test inside startCommand describe (#66) * feat(cli): add --force flag to focus add - AddIO.rmDir? + getBricksDir? optional methods for dir purge - forcePurgeBrick helper: wipes corrupted pkg dir, removes from state, then re-installs — skips the "already installed" guard - addCommand/addManyCommand forward force flag - Tests: force-reinstall, no-already-installed message, rmDir invocation, bundle brick cascade (tools=0, deps>0) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): add focus reinstall command focus reinstall <X> [Y Z ...] — alias for remove + add --force that preserves the brick's enabled state. Useful for bulk recovery after `focus doctor` detects corrupted installs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): focus doctor --fix flag When --fix is passed, doctor auto-remediates: - Corrupted installs (pkg dir missing, dist missing, invalid manifest, lock entry missing) → focus reinstall <name> - Missing declared dependencies → focus add <dep> Version drift is intentionally NOT auto-fixed (use focus upgrade). Prints actions taken and re-runs doctor at the end to show updated state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): actionable error on Missing dependency at start time When loadBricks reports a failure with a 'Missing dependency "X"' message, enrich the stderr output with three actionable commands: focus add X # install the missing dep focus reinstall Y # if Y's install is corrupted focus doctor # full diagnostic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): cascade auto-deps for bundle bricks + wire reinstall/force/doctor-fix to CLI - focus add [-f/--force] <name>: parse force flag, wire rmDir/getBricksDir - focus reinstall <name> [...]: new command wired through runReinstall - focus doctor [--fix]: parse --fix flag, re-run after fixes in text mode - HELP text updated with all new flags and commands - Bundle bricks verified: tools=[] + deps>0 cascades identically to normal bricks (resolveDeps is agnostic to tools count) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(release): cli 1.8.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(cli): move enrichStartError test inside startCommand describe block The test was outside the describe block and used process.emit('SIGINT'), triggering process.exit(0) and causing vitest to exit with code 1. Moved inside the block where stderr.write is already mocked by beforeEach. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): FOCUS_BENCH_MODE env var skips meta tools for bench isolation (#68) When FOCUS_BENCH_MODE=true (or 1), the focus_list, focus_load, focus_unload, focus_reload, focus_search, focus_install, focus_remove, focus_update, focus_catalog_add, focus_catalog_list, and focus_catalog_remove tools are not registered. Brick tools loaded via center.json are still exposed as usual. Default behaviour (env var absent) is unchanged. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: replace aspirational slogan with measured token savings (#69) Remove unverified "200k to ~2k" claim; replace with 65.9% measured benchmark figure with link to full equivalence report. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: implement focus_update + focus_upgrade MCP tools + CLI update alias (#70) * feat(start): implement focus_update MCP tool reusing upgradeCommand Replace the stub with a real implementation that delegates to upgradeCommand. Schema updated to accept brick (string), all (boolean), check (boolean). Tests cover happy path, single brick, dry-run (--check), and error cases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(cli): add 'update' alias to 'upgrade' command for consistency with MCP tool focus update <brick> and focus update --all now work as aliases for focus upgrade, following npm conventions (npm update / npm upgrade). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(add): mention both 'focus upgrade' and 'focus update' in already-installed error Update the error message so users know both aliases are valid options after the 'update' alias was added to the CLI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(start): add focus_upgrade MCP tool as alias for focus_update Both tools share the same upgradeCommand implementation. focus_upgrade returns 'Upgrade failed' prefix vs 'Update failed' for clarity. Tests cover happy path, --check dry-run, and error case for focus_upgrade. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(ci): add back-merge workflow to auto-sync main → develop (#71) Co-authored-by: claude <claude@localhost> * refactor(upgrade): thin wrapper around core.executeUpgrade (#72) * refactor(upgrade): thin wrapper around core.executeUpgrade Moves orchestration logic to @focus-mcp/core/marketplace/upgrader. CLI command now loads the catalog then delegates to core.executeUpgrade. MCP tools (focus_update, focus_upgrade) in start.ts continue to call upgradeCommand which in turn calls core — no breaking change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(deps): pin @focus-mcp/core to 0.0.0-dev.35 for executeUpgrade Interim until @focus-mcp/core@1.2.0 is released to npm latest. Will be bumped to ^1.2.0 in a follow-up release PR. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ci): dev-publish uses changeset snapshot for proper next-version preview tags (#73) Replace custom base-version+dev.N versioning with `pnpm changeset version --snapshot dev` so that the dev dist-tag reflects the actual next stable (e.g. 1.9.0-dev-DATE-SHA) instead of a frozen or mismatched base version. Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(release): @focus-mcp/cli 1.8.1 — bench mode + core 1.2.0 (#74) * chore: bump @focus-mcp/core to ^1.2.0 for executeUpgrade/planUpgrade thin wrapper Required for focus_update + focus_upgrade MCP tools (thin wrapper depends on executeUpgrade exported from @focus-mcp/core 1.2.0). * chore(release): bump @focus-mcp/cli to 1.8.1 — bench mode + core 1.2.0 dep --------- Co-authored-by: claude <claude@localhost> --------- Co-authored-by: claude <claude@localhost> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
focus add --force/-f: Re-installs even if already present or corrupted. Wipesnode_modules/<pkg>dir before re-installing whenrmDir/getBricksDirare provided.focus reinstall <X> [Y Z ...]: New bulk command — alias for force-remove + add, preservesenabledstate. Intended for post-doctorrecovery.focus add codebaseauto-installs all declared deps even whentools=[]. The existingresolveDepsalready handles this; 4 new tests covering bundle cascade and partial-already-installed scenarios.focus doctor --fix: Auto-remediates corrupted installs (reinstall) and missing deps (add). Does NOT auto-fix version drift. Re-runs doctor after fixes in text mode.Missing dependencyerror:focus startfailure messages forMissing dependency "X"now include three recovery commands.Test plan
pnpm test)pnpm typecheck)pnpm build)focus add -f echoreinstalls an already-installed brickfocus reinstall echoremoves + re-adds, restoring disabled statefocus add codebaseinstalls codebase + all 6 deps (bundle cascade)focus doctor --fixremediates corrupted installs and missing depsfocus startwith a Missing dependency emits actionable suggestions🤖 Generated with Claude Code