Skip to content

Make install.ps1 work on standard Windows (no admin): junctions + copy, stop deleting the clone#23

Open
plohkoon wants to merge 2 commits into
mainfrom
fix/windows-install-self-delete
Open

Make install.ps1 work on standard Windows (no admin): junctions + copy, stop deleting the clone#23
plohkoon wants to merge 2 commits into
mainfrom
fix/windows-install-self-delete

Conversation

@plohkoon

@plohkoon plohkoon commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Makes install.ps1 actually work on a standard Windows account. Two commits:

1. Stop deleting the cloned repo

The documented flow clones into the final location and then runs the installer, so the ghostai repo link's Source and Target are the same path ($HOME\.claude\skills\ghostai). New-GhostLink only skipped removal when the target was already a symlink — against the freshly cloned real directory it fell through to Remove-Item -Recurse -Force and deleted the checkout, then tried to link to the now-missing source. install.sh avoids this by comparing resolved real paths; this adds the same self-path guard. Also makes reparse-point removal non-recursive so re-running the installer can't follow a directory link and wipe the real repo (a Remove-Item -Recurse footgun in Windows PowerShell 5.1).

2. Use junctions + copy instead of symlinks (no admin / Developer Mode)

This is what the original PR got wrong: symbolic links on Windows require admin rights or Developer Mode, so installs failed for ordinary users on the symlink step. Switched to privilege-free mechanisms:

  • Directories (repo link, shared/, specialists/, agents/) → directory junctions (New-Item -ItemType Junction). No elevation, transparent to file reads.
  • SKILL.mdcopy. Junctions can't target a file, and a hard link would go stale when git pull replaces the file on update. update.ps1 re-runs install.ps1, which re-copies SKILL.md, so it stays current.

The resulting skill directories are equivalent to the POSIX symlink layout — each has SKILL.md + shared/ (+ specialists//agents/ where present) — so skill discovery and shared/ resolution behave the same. Dropped the symlink-capability preflight and the Developer-Mode/admin error path; README Windows section + troubleshooting updated to say no admin/Developer Mode is needed (just possibly an execution-policy bypass).

Traced flows

Flow Result
Fresh install (clone into final location) repo-link Source==Target → skip; per-skill dirs junctioned, SKILL.md copied ✓
Re-run / update.ps1 junction already correct → skip; stale link → safe non-recursive delete + recreate; SKILL.md re-copied ✓
Clone elsewhere, install into skills repo + dirs junctioned, SKILL.md copied ✓
Leftover symlinks from the earlier broken install detected as reparse points and safely replaced ✓

Caveats

  • Still reviewed-not-executed — no PowerShell on my machine. The logic is straightforward but a smoke test on real Windows (fresh install → second install → update.ps1, as a non-admin user) is the right gate.
  • Anyone who ran the original (pre-fix) installer had their clone deleted and must re-git clone before installing again.

🤖 Generated with Claude Code

plohkoon and others added 2 commits June 16, 2026 14:15
The documented Windows flow clones the repo straight into its final
location ($HOME\.claude\skills\ghostai) and then runs install.ps1. When
the installer links the repo, the repo-link's Source and Target are the
same path. New-GhostLink only skipped removal when the target was already
a symlink, so against the real cloned directory it fell through to
Remove-Item -Recurse -Force and deleted the checkout — then tried to
symlink to the now-missing source. install.sh never hit this because it
compares the resolved real paths of source and target.

Fixes:
- Self-path guard: if the target resolves to the same real path as the
  source, return without touching it (matches install.sh's behavior and
  preserves the freshly cloned repo).
- Symlink-safe removal: delete a reparse point non-recursively. Remove-Item
  -Recurse on a directory symlink in Windows PowerShell 5.1 follows the link
  and deletes the target's contents, so re-running install (or update.ps1's
  re-link) could have wiped the real shared/ directory.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Symbolic links on Windows require admin rights or Developer Mode, so the
symlink-based installer failed for ordinary users. Switch to mechanisms that
work for a standard user:

- Directories (the repo link, shared/, specialists/, agents/) -> directory
  junctions (New-Item -ItemType Junction). Junctions are reparse points that
  need no elevation and are transparent to file reads.
- SKILL.md -> a copy. Junctions can't target files; a hard link would go stale
  when git replaces the file on update. update.ps1 re-runs install.ps1, which
  re-copies SKILL.md, so it stays current.

The resulting skill directories are equivalent to the POSIX (symlink) layout:
each holds SKILL.md plus shared/ (and specialists/ and agents/ where present),
so skill discovery and shared/ resolution work the same.

Also drops the up-front symlink-capability gate and the Developer Mode/admin
error path (no longer relevant), keeps the self-path guard and the
non-recursive reparse-point deletion (which now also cleans up symlinks left
by the earlier symlink-based install), and updates the README Windows section
and troubleshooting to state no admin/Developer Mode is required.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@plohkoon plohkoon changed the title Fix install.ps1 deleting the cloned repo on install Make install.ps1 work on standard Windows (no admin): junctions + copy, stop deleting the clone Jun 17, 2026
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.

1 participant