Skip to content

fix(cua-driver-rs)(skills): home_dir uses .cua-driver/ + sweeps stale .cua-driver-rs/ + repairs dangling links - #1683

Merged
f-trycua merged 1 commit into
mainfrom
skills-home-dir-no-rs
May 24, 2026
Merged

fix(cua-driver-rs)(skills): home_dir uses .cua-driver/ + sweeps stale .cua-driver-rs/ + repairs dangling links#1683
f-trycua merged 1 commit into
mainfrom
skills-home-dir-no-rs

Conversation

@f-trycua

@f-trycua f-trycua commented May 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

User reported `cua-driver skills install` placing the skill pack at `~/.cua-driver-rs/skills/cua-driver/` — even though we renamed `SKILL_PACK_NAME` from `cua-driver-rs` → `cua-driver` in #1677. Root cause: `skills.rs::home_dir()` still hardcoded `.cua-driver-rs/` as the package-home subdir, inconsistent with `telemetry.rs` which migrated to `.cua-driver/` in v0.2.16.

Three changes

1. `home_dir()` defaults to `~/.cua-driver/`

Lifted the same `HOME_SUBDIRECTORY` / `LEGACY_HOME_SUBDIRECTORY` constants telemetry.rs already uses. `CUA_DRIVER_RS_HOME` env override still wins.

2. `sweep_legacy_skill_pack()` cleans three legacy shapes

Path Reason
`/skills/cua-driver-rs/` old pack NAME under new home (already swept since #1677)
`/skills/cua-driver/` new pack NAME under old home — the user's case
`/skills/cua-driver-rs/` old NAME under old home

Then attempts to remove the empty `/skills/` + `/` themselves — but only if they're empty (`fs::remove_dir`, never `remove_dir_all`), so a legacy Unix install that still has a packages/ tree alongside keeps its dot-folder.

3. `link_agent()` repairs dangling links

After the sweep, the agent dir (`~/.claude/skills/cua-driver`) holds a junction pointing at a now-deleted target. The old guard `if link.exists() || symlink_metadata().is_ok()` misread that as "already linked, skip" and left it broken. New logic distinguishes three states:

  • `link.exists() = true` → real or valid link (skip)
  • has metadata + !exists + `is_symlink_or_junction` → dangling, remove + recreate
  • real directory (not a symlink/junction) → user-managed (skip)

`is_symlink_or_junction` already gated dangerous removals — never touches a user-managed real dir.

`uninstall --all` similarly extended to sweep the legacy home dir.

End-to-end verified on Windows

```
$ mkdir -p ~/.cua-driver-rs/skills/cua-driver && echo legacy > ~/.cua-driver-rs/skills/cua-driver/SKILL.md
$ mklink /J %USERPROFILE%.claude\skills\cua-driver %USERPROFILE%.cua-driver-rs\skills\cua-driver
$ cua-driver skills install --force
cleaned up legacy local pack at C:\Users\cuademo.cua-driver-rs\skills\cua-driver
✅ Skill pack at C:\Users\cuademo.cua-driver\skills\cua-driver
cleaned up stale Claude Code link at C:\Users\cuademo.claude\skills\cua-driver
✅ linked Claude Code skill at C:\Users\cuademo.claude\skills\cua-driver

$ readlink ~/.claude/skills/cua-driver
/c/Users/cuademo/.cua-driver/skills/cua-driver

$ ls ~/.cua-driver-rs/ || echo gone
gone
```

Test plan

  • Build clean (`cargo build --release` — 0 warnings)
  • `cargo test --test-threads=1 -p cua-driver` — 49/49 pass
  • End-to-end: legacy install → `skills install` → repaired link + cleaned legacy dir
  • Reviewer: same end-to-end on macOS / Linux (Unix symlinks instead of NTFS junctions — code path is identical, just verify the cleanup also removes empty parent dirs cleanly)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved removal of legacy skill pack files and directories during migration and uninstall operations
    • Enhanced symlink and junction detection and management to prevent conflicts and ensure proper link resolution
    • Extended uninstall to comprehensively clean up legacy home directories and configuration files when empty

Review Change Stack

… .cua-driver-rs/ + repairs dangling agent links

User reported `cua-driver skills install` placing the skill pack at
`~/.cua-driver-rs/skills/cua-driver/` even after PR #1677 renamed the
SKILL_PACK_NAME — because skills.rs's home_dir() still hardcoded
`.cua-driver-rs/` as the package-home subdir, inconsistent with
telemetry.rs which migrated to `.cua-driver/` in v0.2.16.

Three changes:

1. **home_dir() now defaults to `~/.cua-driver/`** (lifted the same
   HOME_SUBDIRECTORY / LEGACY_HOME_SUBDIRECTORY constants telemetry.rs
   already uses). `CUA_DRIVER_RS_HOME` env override still wins.

2. **sweep_legacy_skill_pack() expanded** to clean any of three legacy
   shapes:
     - <NewHome>/skills/cua-driver-rs/          (old pack NAME under new home)
     - <LegacyHome>/skills/cua-driver/          (new pack NAME under old home — the user's case)
     - <LegacyHome>/skills/cua-driver-rs/       (old NAME under old home)
   Then attempts to remove the empty `<LegacyHome>/skills/` and
   `<LegacyHome>/` themselves — but only if they're actually empty
   (`fs::remove_dir`, never `remove_dir_all`), so a legacy Unix install
   that still has a packages/ tree alongside keeps its dot-folder.

3. **link_agent() repairs dangling links**, not just creates missing
   ones. After sweep removes the old target, the agent dir
   (`~/.claude/skills/cua-driver` etc.) holds a junction pointing at
   nothing. The old guard `if link.exists() || symlink_metadata.is_ok`
   misread that as "already linked, skip" and left it broken. Now:
     - link.exists() = true                     → real / valid link (skip)
     - has metadata + !exists + is_symlink/junction → dangling, remove + recreate
     - real directory                           → user-managed (skip)

   `is_symlink_or_junction` already gated dangerous removals — never
   touches a user-managed real dir.

`uninstall --all` similarly extended to sweep the legacy home dir.

End-to-end verified on Windows:
  - legacy pack at ~/.cua-driver-rs/skills/cua-driver  ← gone after install
  - stale junction at ~/.claude/skills/cua-driver      ← repaired (now points at
                                                          ~/.cua-driver/skills/cua-driver)
  - new home ~/.cua-driver-rs/                          ← removed (was empty after sweep)
@vercel

vercel Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored May 24, 2026 1:23pm

Request Review

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cbb5ebd2-7694-47be-9cd7-24c4e5673ad3

📥 Commits

Reviewing files that changed from the base of the PR and between ef7e2b6 and 5b3fcdd.

📒 Files selected for processing (1)
  • libs/cua-driver/rust/crates/cua-driver/src/skills.rs

📝 Walkthrough

Walkthrough

This PR updates the cua-driver skills module to standardize home directory constants, expand legacy skill-pack cleanup across both current and legacy on-disk locations, improve symlink/junction resolution, and extend uninstall behavior to remove now-empty legacy directories.

Changes

Skill pack migration and legacy cleanup

Layer / File(s) Summary
Home directory constants and resolution
libs/cua-driver/rust/crates/cua-driver/src/skills.rs
Introduces HOME_SUBDIRECTORY and LEGACY_HOME_SUBDIRECTORY constants and updates home_dir() and legacy_home_dir() to use them consistently; CUA_DRIVER_RS_HOME environment override disables legacy-location resolution by returning None.
Legacy skill-pack sweep expansion
libs/cua-driver/rust/crates/cua-driver/src/skills.rs
Rewrites sweep_legacy_skill_pack() to remove legacy-named packs from both current-home and legacy-home directories, and attempts removal of empty legacy skills/ and home directories while preserving existing agent symlink/junction cleanup behavior.
Agent symlink and junction handling
libs/cua-driver/rust/crates/cua-driver/src/skills.rs
Updates link_agent() to compute symlink metadata and resolution state, distinguishing between already-linked-resolves and dangling symlink/junction cases (dangling links are removed and recreated) while avoiding real-directory clobbering.
Uninstall command legacy cleanup
libs/cua-driver/rust/crates/cua-driver/src/skills.rs
Extends uninstall --all to remove legacy-home skill packs after local removals, then attempts cleanup of legacy skills/ and home directories when empty.

Possibly related PRs

  • trycua/cua#1677: Both PRs modify libs/cua-driver/rust/crates/cua-driver/src/skills.rs to rename/standardize the skill-pack (cua-driver vs cua-driver-rs) and to expand legacy cleanup during install/uninstall (via legacy sweep/removal logic), so the main PR's legacy migration/uninstall changes build directly on the same skills.rs migration surface.

  • trycua/cua#1366: The main PR updates the Rust cua-driver skills home/legacy resolution and uninstall/migration logic for local skill pack directories, which overlaps with the retrieved PR's installer/uninstaller handling of the same ~/.claude/skills/cua-driver pack/symlink created from the bundled app.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 The skills pack found its rightful home,
No longer lost cua-driver-rs to roam,
Legacy symlinks untangled and neat,
Dangling threads cleaned from old sheet,
One migration dance, legacy swept complete! 🎭

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch skills-home-dir-no-rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@f-trycua
f-trycua merged commit f474a3e into main May 24, 2026
5 of 7 checks passed
@f-trycua
f-trycua deleted the skills-home-dir-no-rs branch May 24, 2026 13:24
f-trycua added a commit that referenced this pull request May 26, 2026
…ver/ home (matches v0.2.16+ runtime) (#1711)

Picks up the home-dir rename that landed in v0.2.16 (PR #1644) but
missed this Bash dev-installer helper. Before this fix, every
`./install-local.sh` on macOS/Linux re-created a stale
`~/.cua-driver-rs/` directory parallel to the canonical
`~/.cua-driver/` (the runtime sweeps the legacy path on first call but
the local installer kept planting fresh copies).

Changes:

- `HOME_DIR` defaults to `${CUA_DRIVER_HOME:-${CUA_DRIVER_RS_HOME:-$HOME/.cua-driver}}`.
  The legacy `CUA_DRIVER_RS_HOME` env var is still accepted so any
  dev scripts that set it keep working.
- Same backcompat for `CUA_DRIVER_INSTALL_DIR` / `CUA_DRIVER_BIN_DIR`
  (the `_RS_` variants remain accepted as fallbacks).
- LaunchAgent label: `com.trycua.cua-driver-rs` →
  `com.trycua.cua-driver`. Same .plist filename change.
- systemd user unit: `cua-driver-rs.service` → `cua-driver.service`.

Plus three sweep blocks that delete the pre-rename artefacts:
  1. `~/.cua-driver-rs/` directory (unconditional, only if HOME_DIR
     differs — so users with the env var set keep their override).
  2. The legacy LaunchAgent plist (unloaded + removed before the new
     plist is written, so the new label doesn't race the old one).
  3. The legacy systemd unit (disabled + removed before the new unit
     is written, same race-avoidance).

The runtime already sweeps the legacy home on first invocation (see
telemetry.rs::migrate_legacy_telemetry_home + the LEGACY_HOME_SUBDIRECTORY
constant introduced in PR #1644 / #1683) so this fix is belt-and-braces
on the installer side. After this PR ships:
  - Existing developers re-running `./install-local.sh` get the legacy
    home dir cleaned up automatically.
  - New installs only ever plant the canonical `~/.cua-driver/`.

Tested locally on this Mac (arm64-apple-darwin):
  $ ls -d ~/.cua-driver-rs                # → does not exist (swept)
  $ ls -la ~/.cua-driver/packages/current  # → symlink to ../releases/0.0.0-local-debug-arm64-apple-darwin
  $ ~/.local/bin/cua-driver --version      # → cua-driver 0.2.18

Header comments / banner / staged-skills paths that contain the
verbatim string "cua-driver-rs" as a project identifier (not a path)
intentionally retained — that's still the cargo crate name + the
historical home subdir name in skill-pack staging. Only the *user-
visible install paths* changed.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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