Skip to content

Detect file renames without triggering deletions#587

Merged
huntercaron merged 26 commits intomainfrom
feature/code-link-rename-detection
Mar 12, 2026
Merged

Detect file renames without triggering deletions#587
huntercaron merged 26 commits intomainfrom
feature/code-link-rename-detection

Conversation

@huntercaron
Copy link
Collaborator

@huntercaron huntercaron commented Mar 6, 2026

Description

This PR implements proper file rename detection in the code-link CLI and fixes the echo event bug that was causing false deletions. The changes include:

  1. Rename Detection: Detects when chokidar emits unlink + add events for the same content (indicating a rename) and emits a single "rename" event instead
  2. Rename API Usage: Uses Framer's codeFile.rename() API to properly rename files without deletion
  3. Sanitization Echo Suppression: Suppresses the false echo events that chokidar fires when the watcher itself renames files for sanitization (e.g., race?.tsxrace_.tsx or New Folder With Items/New_Folder_With_Items/)

Without the echo suppression fix, renaming files locally would trigger a delete operation on the remote plugin, undoing the rename. The 100ms buffer for rename detection ensures that both unlink and add events are matched regardless of their arrival order.

Drive-by improvements

  • Added tests for the plugin-side api.ts (rename, delete, sync operations)
  • Refactored code file name normalization into a shared normalizedCodeFileName() helper to reduce duplication
  • Improved test typing
  • Minor import re-ordering

Changelog

  • Added rename detection based on content hash matching with 100ms buffer
  • Implemented file-rename message type for CLI-to-plugin communication
  • Added SEND_FILE_RENAME effect in CLI controller to handle rename events
  • Added applyRemoteRename() method in plugin API using Framer's codeFile.rename()
  • Added sanitization echo suppression to prevent false deletes after path sanitization
  • Added same-path rename guard for defensive-in-depth

Testing

  • Renaming files locally renames them in Framer (no deletion modals shown)
  • Moving files in and out of folders locally works as expected

@huntercaron huntercaron added Auto submit to Marketplace on merge Submits the plugin to the marketplace after merging and removed Auto submit to Marketplace on merge Submits the plugin to the marketplace after merging labels Mar 6, 2026
@Nick-Lucas Nick-Lucas requested a review from Copilot March 6, 2026 12:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds end-to-end rename support to the code-link workflow (CLI watcher → CLI controller → plugin) by detecting unlink+add rename patterns locally, sending a new file-rename message type, and applying the rename remotely via Framer’s codeFile.rename() API. It also adds suppression for chokidar “echo” events caused by the watcher’s own sanitization renames to avoid false remote deletions.

Changes:

  • Add hash-based unlink+add pairing with a short buffer to emit a single local rename watcher event.
  • Introduce file-rename CLI→plugin message + controller effect to send renames and update local tracking.
  • Implement plugin-side remote rename application via codeFile.rename() and update shared message types accordingly.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
plugins/code-link/src/api.ts Adds applyRemoteRename() to rename Framer code files and acknowledge via file-synced.
plugins/code-link/src/App.tsx Handles incoming file-rename messages and invokes the new API method.
packages/code-link-shared/src/types.ts Extends shared message union/validation to include file-rename.
packages/code-link-cli/src/utils/project.ts Adjusts directory-name sanitization rules (now preserves spaces).
packages/code-link-cli/src/utils/hash-tracker.ts Reuses shared hashing utility from state persistence (removes local crypto hashing).
packages/code-link-cli/src/types.ts Adds rename watcher event kind and oldRelativePath metadata.
packages/code-link-cli/src/helpers/watcher.ts Implements rename detection + sanitization echo suppression + buffer cleanup on close.
packages/code-link-cli/src/helpers/watcher.test.ts Adds unit tests covering rename detection, buffering, and echo suppression.
packages/code-link-cli/src/helpers/installer.ts Minor formatting cleanup (whitespace).
packages/code-link-cli/src/helpers/files.test.ts Adjusts test typings for conflict content values.
packages/code-link-cli/src/controller.ts Adds rename handling in the state machine and a new SEND_FILE_RENAME effect.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@huntercaron
Copy link
Collaborator Author

Dang ok I guess I will start doing copilot + devin + cursor haha

@huntercaron
Copy link
Collaborator Author

@cursor review

@huntercaron
Copy link
Collaborator Author

@devin are you here to review

@huntercaron
Copy link
Collaborator Author

This PR has become testing grounds for how cursor bugbot kinda sucks at finding things in one pass and loves to go in circles

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

@huntercaron
Copy link
Collaborator Author

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

export function toDirectoryName(name: string): string {
return name
.replace(/[^a-zA-Z0-9-]/g, "-")
.replace(/[^a-zA-Z0-9- ]/g, "-")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ambiguous regex character class relies on legacy parsing

Low Severity

The character class [^a-zA-Z0-9- ] contains an ambiguous - between 9 and (space). JavaScript parses this as a range from - (ASCII 45) to (ASCII 32), which is invalid since the start exceeds the end. In non-unicode mode this silently falls back to treating both as literal characters, but adding the u flag would cause a SyntaxError. Placing the hyphen at the end of the class (e.g., [^a-zA-Z0-9 -]) would make the intent unambiguous and work in both modes. The PR discussion also notes this is "a bit stinky."

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Copy link
Contributor

@Nick-Lucas Nick-Lucas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving + ticking QA on the basis that this is an in development plugin and still being shaken down and improved as we go. Lots of review bots too so let's favour forward motion though I don't have time to QA/review properly

@huntercaron huntercaron force-pushed the feature/code-link-rename-detection branch from 4503ed9 to 553d7af Compare March 12, 2026 11:16
@huntercaron huntercaron added this pull request to the merge queue Mar 12, 2026
Merged via the queue into main with commit 00624f9 Mar 12, 2026
6 checks passed
@huntercaron huntercaron deleted the feature/code-link-rename-detection branch March 12, 2026 11:24
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.

3 participants