{"record":{"id":"08320d5a1dbe3eed","repo":"ReactiveX/rxjs","slug":"refusing-to-remove-a-locally-modified-skill-copy-a","errorCode":null,"errorMessage":"Refusing to remove a locally modified Skill copy at ${installation.targetPath} without explicit force.","messagePattern":"Refusing to remove a locally modified Skill copy at (.+?) without explicit force\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/migrate/src/skill-install.ts","lineNumber":143,"sourceCode":"}\n\nexport async function updateSkill(options: SkillInstallOptions): Promise<SkillInstallResult> {\n  const installation = await resolveInstallation(options);\n  const state = await installationState(installation);\n  if (state === 'current') return resultFor('update', installation, state, state, false);\n  if (state === 'modified' && !options.force) {\n    throw new Error(`Refusing to overwrite a locally modified Skill copy at ${installation.targetPath} without explicit force.`);\n  }\n  await replaceInstallation(installation);\n  return resultFor('update', installation, state, 'current', true);\n}\n\nexport async function removeSkill(options: SkillInstallOptions): Promise<SkillInstallResult> {\n  const installation = await resolveInstallation(options);\n  const state = await installationState(installation);\n  if (state === 'absent') return resultFor('remove', installation, state, state, false);\n  if (state === 'modified' && !options.force) {\n    throw new Error(`Refusing to remove a locally modified Skill copy at ${installation.targetPath} without explicit force.`);\n  }\n  await rm(installation.targetPath, { recursive: true, force: false });\n  return resultFor('remove', installation, state, 'absent', true);\n}\n\nexport function manageSkillInstallation(action: SkillInstallAction, options: SkillInstallOptions): Promise<SkillInstallResult> {\n  switch (action) {\n    case 'check':\n      return checkSkillInstallation(options);\n    case 'install':\n      return installSkill(options);\n    case 'update':\n      return updateSkill(options);\n    case 'remove':\n      return removeSkill(options);\n  }\n}\n","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/ReactiveX/rxjs/blob/54796b38a57e6309f9861e174737479bb3f63f61/packages/migrate/src/skill-install.ts#L125-L161","documentation":"Thrown by removeSkill when the installed skill copy is locally modified and --force is absent. Removing would delete uncommitted user edits, so explicit force is required as confirmation.","triggerScenarios":"Running rxjs-migrate-skill remove after editing the installed skill files, without --force.","commonSituations":"Cleaning up after customizing the skill; uninstalling during migration rollback while local edits exist.","solutions":["Back up the modified copy first, then rerun remove with --force","If edits are disposable, remove with --force directly","Reconsider removal if the edits contain work you still need"],"exampleFix":"# before\nrxjs-migrate-skill remove --harness claude\n# after\nrxjs-migrate-skill remove --harness claude --force","handlingStrategy":"try-catch","validationCode":"const modified = await detectModifiedSkillCopy(targetPath);","typeGuard":null,"tryCatchPattern":"try { removeSkill(opts); } catch (e) { if (e instanceof Error && e.message.includes('locally modified')) { /* archive copy, retry with force */ } throw e; }","preventionTips":["Archive skill edits before removal","Confirm you no longer need edits before forcing"],"tags":["cli","skill-install","safety-guard","deletion-protection"],"backgroundTag":"refusing-delete-modified-file","analyzedSha":"54796b38a57e6309f9861e174737479bb3f63f61","analyzedAt":"2026-08-28T10:21:27.410Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}