Skip to content

fix: Windows compatibility for install.sh and onboarding wizard - #1

Merged
codejunkie99 merged 1 commit into
codejunkie99:masterfrom
JagritGumber:fix/windows-compat
Apr 16, 2026
Merged

fix: Windows compatibility for install.sh and onboarding wizard#1
codejunkie99 merged 1 commit into
codejunkie99:masterfrom
JagritGumber:fix/windows-compat

Conversation

@JagritGumber

Copy link
Copy Markdown
Contributor

Summary

Two Windows-only bugs prevent ./install.sh claude-code from working on a fresh clone.

1. Onboarding wizard crashes on import. onboard_ui.py imports tty and termios unconditionally, but both are POSIX-only, so Python on Windows errors out with ModuleNotFoundError: No module named 'termios' before any wizard code runs. Fixed by branching the raw key reader on sys.platform: msvcrt.getwch() on Windows (with \x00 / \xe0 arrow-key prefix handling), existing tty/termios path on POSIX.

2. install.sh shebang gets CRLF on Windows clones. With Git's default core.autocrlf=true, the shebang becomes #!/usr/bin/env bash\r, which bash reports as /usr/bin/env: 'bash\r': No such file or directory. Fixed by adding .gitattributes pinning .sh and .py to text eol=lf.

Existing Windows checkouts will need a re-clone (or git rm --cached -r . && git reset --hard) to pick up the new eol rules. No behavior change on macOS or Linux.

onboard_ui.py imported tty and termios unconditionally. Both are Unix-only, so the wizard crashed on import under Windows Python before any logic ran. Branch the raw key reader on sys.platform: use msvcrt.getwch on Windows (handling the 0x00 / 0xe0 arrow-key prefix), keep the existing tty/termios path on POSIX.

Add .gitattributes forcing LF on .sh and .py so Git core.autocrlf=true on Windows clones does not rewrite shell script shebangs to CRLF (previously caused /usr/bin/env: 'bash\r': No such file or directory when invoking install.sh from Git Bash or WSL).
@codejunkie99 codejunkie99 self-assigned this Apr 16, 2026
@codejunkie99
codejunkie99 merged commit 6b8f457 into codejunkie99:master Apr 16, 2026
@codejunkie99

Copy link
Copy Markdown
Owner

approve

codejunkie99 pushed a commit that referenced this pull request Apr 21, 2026
fix(claude-code): replace hardcoded hook with rich episodic logging
codejunkie99 pushed a commit to hovhannest/agentic-stack that referenced this pull request Apr 23, 2026
Cross-model review (Claude + Codex adversarial) flagged 4 issues that
would either lose user data on Windows or silently degrade episodic
memory quality.

1. install.ps1:157-159 — DATA LOSS on Windows re-install.
   `Remove-Item -LiteralPath $skillsDst -Recurse -Force` on PowerShell
   5.1 (default Windows shell) traverses INTO a symlink target and
   deletes its contents before removing the link. A second
   `install.ps1 pi` run would wipe .agent/skills/. Detect ReparsePoint
   via Get-Item.Attributes BEFORE Remove-Item; use
   .NET Directory.Delete($path, false) on links so only the link is
   removed, never the target.

2. adapters/pi/memory-hook.ts — no subprocess timeout, hangs Pi.
   `await runHook(payload)` is awaited inside Pi's tool_result handler;
   a stuck Python child blocks Pi's event loop forever. Add 3s default
   timeout (overridable via $AGENT_HOOK_TIMEOUT_MS), kill the child on
   timeout, surface `timeout` as a separate result kind.

3. adapters/pi/memory-hook.ts — stderr was dropped, failures
   undiagnosable. Switch stdio to capture stderr (bounded to 4KB to
   avoid memory blowup on a wedged hook) and surface the first line
   in the failure notification.

4. .agent/harness/hooks/pi_post_tool.py — Pi sends tool_input with
   camelCase keys (filePath, oldString, newString), but the shared
   cc.* helpers (action_label, reflection, importance) expect Claude
   Code's snake_case keys. Without normalization, every Edit/Write
   logged by Pi degraded to "edit: ?" / "Edited ?" with empty detail.
   Add a Pi→canonical input key map applied in _normalize_input().

5. .agent/harness/hooks/pi_post_tool.py — fail-open on malformed
   payload was logging bogus "Unknown success" entries (Codex's High
   codejunkie99#1). If Pi ever changes the event shape or sends invalid JSON,
   episodic memory got polluted with noise instead of a real signal.
   Add a _emit_malformed() path that records an explicit
   `hook:malformed_payload` failure entry with a 200-char excerpt of
   the offending payload — visible in AGENT_LEARNINGS.jsonl as a real
   error, not noise.

Smoke-tested:
- empty payload → `hook:malformed_payload | empty payload`
- malformed JSON → `hook:malformed_payload | json decode error: ...`
- Pi camelCase Edit (filePath/oldString/newString) → produces correct
  `edit: /tmp/x.txt` action label and `Edited /tmp/x.txt: replaced 'a'
  with 'b'` reflection (was: `edit: ?` / `Edited ?`)
- well-formed bash success → unchanged behavior

Codex's concurrent-write concern (Codex codejunkie99#3) and the rsync-style sync
for .pi/skills (Codex codejunkie99#5) are NOT addressed here — they apply to
pre-existing infrastructure (post_execution.py write semantics, pi's
existing symlink path) and are scoped as separate follow-ups.
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.

2 participants