After upstream switched to SEA (Single Executable Application) layout
in v2.1.114+, there is no cli.js anymore — only bin/claude.exe.
Before this fix:
- find_cli_js() searched only for cli.js → returned None on SEA installs
- get_installed_version() returned (None, None) → "Claude Code: not installed"
- is_patched() returned (False, [3 markers]) → false-negative even after
successful patch
- cmd_check showed "not installed" right after a successful update
- cmd_update would loop reinstalling because patch markers seemed missing
This contributed to a user-facing incident where /model picker showed
only built-in models even though CLAUDE_CUSTOM_MODELS was set in
settings.json: the binary update path was triggering uninstall+reinstall
cycles instead of being recognised as already-patched.
Changes:
- New find_claude_artifact() finds either cli.js or bin/claude.exe,
including the deeply-nested layout npm uses for SEA wrapper packages
- find_all_cli_js() returns both legacy and SEA artifacts
- is_patched() auto-detects layout: text scan for cli.js, bytes scan
for claude.exe (markers: /*ae1_models_filter_patched*/,
/*bypass_permissions_prompt*/)
- get_installed_version() reads package.json next to bin/ for SEA
- uclaude_install.sh adds binary marker verification at end of install
so users immediately see if the SEA payload was patched
Tests: new tests/test_sea_detect.py covers all 4 detector functions
against fake SEA install layouts (including nested form). All 20 tests
pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>