MCPcopy Index your code
hub / github.com/github/spec-kit / remove

Method remove

src/specify_cli/extensions/__init__.py:1533–1609  ·  view source on GitHub ↗

Remove an installed extension. Args: extension_id: Extension ID keep_config: If True, preserve config files (don't delete extension dir) Returns: True if extension was removed

(self, extension_id: str, keep_config: bool = False)

Source from the content-addressed store, hash-verified

1531 )
1532
1533 def remove(self, extension_id: str, keep_config: bool = False) -> bool:
1534 """Remove an installed extension.
1535
1536 Args:
1537 extension_id: Extension ID
1538 keep_config: If True, preserve config files (don't delete extension dir)
1539
1540 Returns:
1541 True if extension was removed
1542 """
1543 if not self.registry.is_installed(extension_id):
1544 return False
1545
1546 # Get registered commands and skills before removal
1547 metadata = self.registry.get(extension_id)
1548 registered_commands = (
1549 metadata.get("registered_commands", {}) if metadata else {}
1550 )
1551 raw_skills = metadata.get("registered_skills", []) if metadata else []
1552 # Normalize: must be a list of plain strings to avoid corrupted-registry errors
1553 if isinstance(raw_skills, list):
1554 registered_skills = [s for s in raw_skills if isinstance(s, str)]
1555 else:
1556 registered_skills = []
1557
1558 extension_dir = self.extensions_dir / extension_id
1559
1560 # Unregister commands from all AI agents
1561 if registered_commands:
1562 registrar = CommandRegistrar()
1563 registrar.unregister_commands(registered_commands, self.project_root)
1564
1565 # Unregister agent skills
1566 self._unregister_extension_skills(registered_skills, extension_id)
1567
1568 if keep_config:
1569 # Preserve config files, only remove non-config files
1570 if extension_dir.exists():
1571 for child in extension_dir.iterdir():
1572 # Keep top-level *-config.yml and *-config.local.yml files
1573 if child.is_file() and (
1574 child.name.endswith("-config.yml")
1575 or child.name.endswith("-config.local.yml")
1576 ):
1577 continue
1578 if child.is_dir():
1579 shutil.rmtree(child)
1580 else:
1581 child.unlink()
1582 else:
1583 # Backup config files before deleting
1584 if extension_dir.exists():
1585 # Use subdirectory per extension to avoid name accumulation
1586 # (e.g., jira-jira-config.yml on repeated remove/install cycles)
1587 backup_dir = self.extensions_dir / ".backup" / extension_id
1588 backup_dir.mkdir(parents=True, exist_ok=True)
1589
1590 # Backup both primary and local override config files

Calls 7

unregister_commandsMethod · 0.95
unregister_hooksMethod · 0.95
HookExecutorClass · 0.85
CommandRegistrarClass · 0.70
is_installedMethod · 0.45
getMethod · 0.45