Release 1.9.8 (aicodeman) and 0.1.8 (xterm-zerolag-input). Fixes macOS session start (`posix_spawnp failed.`, issues #6 and #204): node-pty ships its macOS spawn-helper as mode 0644 and macOS launches every PTY through it. `scripts/fix-node-pty.mjs` (npm run fix:node-pty) chmods every helper, prebuilds/ included, then verifies by really opening a PTY; the blind Node-22+ rebuild is gone. `spawnPtyWithHelperRepair()` self-heals an already broken install on the first failed spawn. Adds the phone home screen (session overview under 430px, per-device `mobileOverviewEnabled`, default ON) and a guided Tailscale path in install.sh, plus `install.sh tailscale` to retrofit it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
9.1 KiB
xterm-zerolag-input
0.1.8
Patch Changes
-
Fixed: sessions failed to start on macOS with
Error: posix_spawnp failed.(issues #6 and #204)node-pty@1.1.0publishes its macOS prebuilt helper asprebuilds/darwin-<arch>/spawn-helperwith mode 0644, i.e. no execute bit. macOS launches every PTY through that helper, so a stock install failed on every session start. The bug is macOS-only:spawn-helperis a mac-only gyp target and node-pty ships no Linux prebuild, so Linux always compiles a correctly-permissioned helper from source.The previous fix chmodded only
build/Release/spawn-helper, which on macOS does not exist (the prebuild is used, so node-gyp never runs), and it derived that path fromrequire.resolve('node-pty'), landing on<pkg>/lib/build/Release/.... It was a no-op on every platform.- New
scripts/fix-node-pty.mjs(alsonpm run fix:node-pty) chmods everyspawn-helperit finds, inbuild/Release,build/Debugand eachprebuilds/*/, then verifies the result by actually opening a PTY. Arequire()alone passes on a broken install, because the helper is only touched at spawn time. postinstallno longer force-rebuilds node-pty from source on Node 22+. That step needed Xcode command line tools, cost 30-120s on every install, and deleted theprebuilds/tree before compiling, so a Mac without a compiler was left with no working binary at all. A rebuild now happens only when the chmod plus spawn probe still fails, and the prebuilds tree is backed up and restored around it.- New
spawnPtyWithHelperRepair()(src/utils/node-pty-repair.ts) wraps everypty.spawn()insession.ts, so an install that is already broken repairs itself on the first failed spawn and retries in-process instead of showing a dead session. Unrelated spawn errors are rethrown untouched; a second failure carries thenpm run fix:node-ptyhint. scripts/fix-node-pty.mjsis now in the publishedfileslist, so global npm installs get the repair too.- Direct-PTY Claude spawns use the resolved absolute binary path (new
getClaudeBinaryPath()) instead of the bare nameclaude, so a CLI installed outside the server's PATH still launches.
Verified end to end on macOS 26.4 arm64: a stock
npm ireproducesposix_spawnp failed., and after the fix the same install spawns a PTY successfully with the prebuilds preserved.Added: phone home screen (session overview)
Under 430px the "C" logo now opens a session overview (current sessions, past sessions, spaces) instead of the welcome overlay: on a small screen "which session needs me" beats "how do I start one". Rows resume a session in place, and "New session here" goes through the normal quick-start path so remote and Docker cases keep their routing. Per-device setting
mobileOverviewEnabled(phones only, default ON) in App Settings. Tablet and desktop are unchanged.Added: guided Tailscale setup in
install.shThe network-access prompt is now 3-way: Tailscale, LAN, or local-only. The Tailscale path binds loopback and walks through installing Tailscale, logging in, the operator grant, the tailnet HTTPS-certificates toggle, and
tailscale serve --bg <port>, then verifies the result end to end with curl. That gives HTTPS on a real certificate with no app password and no0.0.0.0bind, which is also what PWA install and web push need.install.sh tailscaleretrofits it onto an existing install, andCODEMAN_TAILSCALE=1presets the choice. Serve state is detected fromtailscale serve status --json; the installer never runstailscale serve resetand never touches serve mappings other than 443 to Codeman's port. README anddocs/security-architecture.mdupdated to match.Docs: replaced a real tailnet hostname with placeholders in
docs/web-tabs-fixes-plan.md.xterm-zerolag-input: npm description and keywords only, no code change.
- New
0.1.7
Patch Changes
- Fix a latent bug where a partial settings PUT silently reset live service state, and trim the
xterm-zerolag-inputREADME callout.PUT /api/settingsno longer resets watchers on a partial body. The threetoggleServicecalls (subagent watcher, workflow-run watcher, image watcher) read the raw request body with??defaults, so every key a caller omitted was treated as "apply the default". A body of just{statusLineTelemetry:true}would START the subagent watcher and STOP the workflow and image watchers, undoing the persisted config. They now resolve frommerged(persisted settings + incoming), the same convention thetmuxHistoryLimitbranch in that handler already used, so any PUT reconciles services to the effective stored state. Nothing triggered this in practice because every shipped client sends a full settings payload rebuilt from the DOM, but it was a trap for the next partial-update caller.- Regression test:
test/routes/system-routes-settings-partial-put.test.ts(4 cases) pins both directions, omitted keys preserve state and explicit keys still take effect. Verified to fail against the pre-fix handler. - CLAUDE.md records the rule under "Adding Features → App setting": anything acting on a setting in that handler must resolve from
merged, never the request body. xterm-zerolag-inputREADME: removed the links line (getcodeman.com / install one-liner / star link) from the Codeman callout above the demo GIF. The callout keeps its links in the heading and body.
0.1.6
Patch Changes
- Plan-usage chip now defaults ON on desktop, plus the reworked
xterm-zerolag-inputREADME.- Plan-usage chip defaults ON (desktop). The
showPlanUsageLimitschip (live 5-hour and weekly plan usage from the Claude statusline) used to be opt-in and default OFF, so most users never saw it. Desktop now defaults ON; handhelds still default OFF so the phone header stays minimal and themobile-header-buttons-policyguard keeps passing. Devices with an explicitly stored preference keep whatever they chose, so nobody's OFF gets overridden. - One resolver behind the chip. Added
planUsageChipEnabled()in settings-ui.js and routed all three call sites through it: the App Settings checkbox, the chip's visibility, and the create-timestatusLineTelemetryflag in session-ui.js. Those three had independent?? false/=== truedefaults, and a chip revealed without the telemetry flag renders—forever, so a default flip on one site alone would have shipped a permanently empty chip. - Cron button comment corrected. The App Settings comment claimed "Cron button defaults ON" while the code, the template (
btn-cron--hidden) and the CSS all default it OFF. Verified against a fresh browser profile: the button is hidden and its checkbox unchecked out of the box. Comment now matches, and states why the two halves stay consistent. - Docs. CLAUDE.md,
docs/architecture-invariants.mdanddocs/usage-limits-display-plan.mdupdated for the new default and the single-resolver rule; the stalestyles.csscomment claiming the server strips the chip's hidden class at render was corrected (display is per-device, so the client reveals it). xterm-zerolag-inputREADME rework (0.1.5 shipped the content; this republishes with the graphic and promo changes): replaced the misaligned 8-line keystroke-flow diagram with a two-line stock-vs-zerolag contrast, added a Codeman callout above the demo GIF with links to getcodeman.com and the repo, and rewrote the Origin section so it argues the extraction story instead of repeating the promo.
- Plan-usage chip defaults ON (desktop). The
0.1.5
Patch Changes
-
Rewrite the
xterm-zerolag-inputpackage README as a value-first document and correct the drift that had accumulated against the source.- Added the side-by-side phone demo GIF (
docs/images/zerolag-demo-20260728.gif) as the hero image, referenced by absolute raw URL so it renders on npmjs.com as well as GitHub. The two-phone comparison shows 0ms local echo next to a 600ms-2.7s server echo on the same session. - New "Why this one" comparison table, an explicit list of target use cases (SSH web clients, cloud IDEs, mobile terminals, container consoles), and a bundle-size badge (6.1 kB gzipped, measured from the ESM build).
- Corrected the test-count badge from 78 to the actual 175 tests across 5 files, in both the package README and the Published Packages section of the root README.
- Removed the stale "Unicode/emoji rendered at single-cell width" limitation. CJK, fullwidth forms and emoji have had double-width rendering and visual-column positioning since the wide-character fix; the honest remaining caveat (per-code-point width summing over-counts ZWJ grapheme clusters) replaces it.
- Documented the previously undocumented public
setPrompt()method for switching prompt strategies at runtime, and the new "Wide characters (CJK, emoji)" integration section covering the optionalUnicode11Addonpath and the built-in range-table fallback. - Documented
backgroundColor: 'transparent', corrected theforegroundColordefault, and updated the grid-alignment math to reflect visual-column positioning rather than character index.
No source changes, docs only.
- Added the side-by-side phone demo GIF (
0.1.4
Patch Changes
- Initial changelog entry for changesets-based versioning