For Windows (run in Git Bash). Goal: extension count to zero + user configuration back to factory.No backups are kept by default(user preference); deletions always go to the Recycle Bin (SendToRecycleBin), never direct physical deletion.
Audit attachment: For all C drive paths handled in past real-world operations (each IDE's extension folders, the personal configuration trio, untouched adjacent directories, recovery guidance), see references/cleanup-audit-log.md. Before executing a new target, refer to this list to confirm the handling boundaries for similar paths; after completing each new cleanup, this list should be appended and updated.
Iron rules (pitfalls already stepped on)
- Choose the right CLI entry point: under the fork's
bin/there are often multiple.cmd(such ascode.cmd、qoder-cn.cmd). Try--list-extensionsone by one; only the one that can output the extension list is the IDE management entry point; the other is most likely a shell for a standalone agent CLI and does not support extension arguments. - Do not guess the data directory:
~/.xxx/extensionsA directory like this may belong toanother product from the same family(shared or historical leftover). The only authoritative source is the<安装目录>/resources/app/product.jsonfield ofdataFolderName. - Built-in imported extensions must
--force: reportingmarked as a Built-in extensionis not a failure; add--forceand retry. - Must scan for residue after uninstall: CLI uninstall leaves empty shell folders,
.GUIDtemp directories and.obsoletemarkers; physical directories must be cleaned manually. - Dependencies will block uninstall: when it reports
Cannot uninstall 'X'. 'Y' extension depends on this, first uninstall the dependent partyY(ifYis built-in "not installed", after the IDE process exits, retryXand it usually goes through); reportingis not installedmeans that item has already been cleared elsewhere, so just skip it; it does not count as a failure. - The IDE process must exit first: a running instance will write back
extensions.jsonand user configuration when it exits, overwriting the cleanup results. Before starting,tasklist | grep -i <IDE名>, if there are processes, have the user close them first. extensions.jsonCounting to 0 is the only completion: the folder was deleted but the registry was not cleared = not cleaned up.- Never touch adjacent product directories: only touch the target fork's own
~/.<dataFolderName>(and only itsextensionssubdirectory) and%APPDATA%\<AppName>\Userthe other directories with the same prefix are other products' homes (.qoder/.qoder-cn/.qoderworkbelong to different products; ownership is based on each one's own product.json). - The CLI uninstall path may be entirely broken: ifallextensions report the same JS error (such as Trae EN's
Cannot read properties of undefined (reading 'isProtectedExtension'), with or without--forceit is the same), it means the fork has broken the uninstall function, not a problem with an individual extension. Do not retry one by one—directly switch to the "direct registry modification plan" (see the fallback branch in standard procedure §3).
Standard procedure
0. Four checks before starting (start gate; if any one fails, do not start)
- Check processes:
tasklist | grep -i <IDE名>, if there are processes, have the user exit first (iron rule 6). - Check entry point: try one by one
bin/*.cmd --list-extensions, and lock onto the extension management CLI (Iron Rule 1). - Check ownership: read
product.json'sdataFolderNameandnameLong, uselsto confirm the actual directory exists (Iron Rule 2). - Check boundaries: enumerate all directories with the same prefix under
~/.<前缀>*and%APPDATA%, list the neighboring product inventory and the agent-layer subdirectories within the target directory (such asagent-extensions/、rules/、skills/、memory/), and make clear that onlyextensions/is to be touched (Iron Rule 8). Show the results of the four checks to the user before taking action. - Check whether the body is genuine: confirm that the target installation directory contains the main program
.exe、resources/app/product.json;An empty directory or an incomplete directory is an empty shell(possibly uninstall residue or a wrong path given), immediately verify the real path with the user, and do not run the process against an empty shell. The same product may have multiple similar paths at the same time (such asai-ide/trae-cnempty shell andai-agent/trae-code-cnreal body), and the path must be verified character by character.
1. Select the CLI entry point
IDE_DIR="<IDE 安装目录>" # 如 "D:/dev-tool/ai-ide/Qoder CN IDE"
for c in "$IDE_DIR"/bin/*.cmd; do
echo "== $c =="; "$c" --list-extensions 2>&1 | head -20
done
CLI="<能列出扩展的那个 .cmd 全路径>"
2. Locate the data directory (product.json is the sole authority)
grep -o '"dataFolderName": *"[^"]*"' "$IDE_DIR/resources/app/product.json"
grep -o '"nameLong": *"[^"]*"' "$IDE_DIR/resources/app/product.json" | head -1
# EXT_DIR = $USERPROFILE/.<dataFolderName>/extensions
# USER_DATA = %APPDATA%\<AppName>\User (AppName 常与 nameLong 一致,大小写以实际目录为准,用 ls 确认)
ls "$USERPROFILE/.<dataFolderName>/extensions" "$APPDATA/<AppName>/User"
When the directory cannot be found: run "$CLI" --help | grep -iA1 "user-data-dir\|extensions-dir" to confirm the parameter name; use ls -d "$USERPROFILE"/.<前缀>* and ls "$APPDATA" | grep -i <前缀> to enumerate candidates; check each candidate for whether extensions/extensions.json exists—the one that exists is the live directory.Better to probe one step further than to delete the wrong directory.
3. Uninstall all extensions (loop + --force)
"$CLI" --list-extensions | tr -d '\r' | while read -r ext; do
echo "== $ext =="
"$CLI" --uninstall-extension "$ext" --force
done
Already factory-state branch: if --list-extensions is empty and extensions.json is already [], it means the plugin layer needs no handling—do not force work to do. Skip directly to §6 verification and confirmation, list the remaining residue (the IDE's own assets, cache, agent layer) for the user to decide whether to delete or keep, and do not expand the scope on your own.
Fallback branch (triggered by Iron Rule 9)—direct registry modification plan:
If all extensions in the previous step report the same JS error (the fork broke the uninstall function), do not retry one by one; directly manually complete the three things the CLI was originally supposed to do:
- First check exemptions: confirm that the physical directory
extensions/does not contain the fork's built-in protection items (ls | grep -iE '<fork前缀>|<其保护清单>'). The protection item list can be found from the whitelist ofisProtectedExtensionin the installation directory source code. If there are none, all can be deleted. - Clear the registry:
printf '[]' > ~/.<dataFolderName>/extensions/extensions.json。 - Clear physical residue: follow the standard process §4 to recycle all extension directories.
- Proceed as usual with §5 / §6: reset configuration + four-evidence verification.
Direct registry modification is equivalent to uninstalling—
extensions.jsonbelongs to[]and after the directory is emptied, the IDE will no longer load any extensions.Same-code-family prediction: different distributions of the same product (such as Trae EN / Trae CN / Trae AICC) share code, and the uninstall pathmaybe broken in the same way. But this is only a probabilistic prediction and cannot be treated as a conclusion—each target must be individually retested once before determining the path(counterexample: Trae EN is all broken, but Trae CN's CLI is completely normal).
4. Clean up physical residue in extension directories (Recycle Bin)
powershell.exe -NoProfile -Command "Add-Type -AssemblyName Microsoft.VisualBasic; Get-ChildItem 'C:\Users\<用户>\.<dataFolderName>\extensions' -Directory | ForEach-Object { [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory(\$_.FullName,'OnlyErrorDialogs','SendToRecycleBin'); Write-Host ('recycled: ' + \$_.Name) }"
# 若残留 .obsolete 标记文件:同法 DeleteFile 回收
5. Reset user configuration (settings.json / keybindings.json / snippets/)
powershell.exe -NoProfile -Command "Add-Type -AssemblyName Microsoft.VisualBasic; \$src = \"\$env:APPDATA\<AppName>\User\"; [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile(\"\$src\settings.json\",'OnlyErrorDialogs','SendToRecycleBin'); [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile(\"\$src\keybindings.json\",'OnlyErrorDialogs','SendToRecycleBin'); [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory(\"\$src\snippets\",'OnlyErrorDialogs','SendToRecycleBin'); Set-Content \"\$src\settings.json\" '{}' -Encoding UTF8; Set-Content \"\$src\keybindings.json\" '[]' -Encoding UTF8; New-Item -ItemType Directory \"\$src\snippets\" | Out-Null"
Parts not to be touched (unless the user explicitly requests a thorough cleanup):globalStorage/、workspaceStorage/— Stores the IDE's own login state and workspace state, not redundant imported configuration.
6. Verification loop (all four pieces of evidence are indispensable)
"$CLI" --list-extensions # 输出必须为空
ls "$USERPROFILE/.<dataFolderName>/extensions" # 只剩空 extensions.json(可含 .obsolete)
cat "$APPDATA/<AppName>/User/settings.json" # {}
cat "$APPDATA/<AppName>/User/keybindings.json" # []
Verification discipline: when capturing the exit code, do not append grep / head or other filters after the command—the pipeline's $? is the filter's exit code, and an empty match returns non-zero, creating a false "failure" report (Trae EN real-world lesson).fork private warnings written to stderr will also dirty the pipeline(such as Antigravity's antigravityAnalytics NOT registered); during verification, use 命令 > /tmp/out 2>/dev/null; echo $? to capture the exit code separately, then check the output file (Antigravity real-world lesson).
Exemption clause: automatically delivered built-in extensions do not need to be handled
Some forks (such as Qoder CN IDE) onstartup will automatically re-deliverbuilt-in extensions marked as "Built-in" (known:ms-python.python / autopep8 / debugpy / vscode-python-envs / detachhead.basedpyright). This is the IDE's own behavior,notpersonal plugins imported by the user from VSCode:
- after uninstalling, as long as that IDE is started again, they will come back (even the version numbers will be renewed), so repeatedly uninstalling is a waste of effort.
- The goal of factory restoration is to clear outredundant imported configuration and plugins; this batch of automatic built-in items does not carry the user's old settings,so exempt them directly and do not handle them。
- During delivery acceptance, just explain this exemption to the user; do not treat it as a cleanup failure.
Optional: completely uninstall the IDE
In the installation directory, unins000.exe(Inno Setup) is the official uninstaller and requires interactive confirmation; prompt the user to run it manually or authorize it separately.
Real-world case (2026-08-31, Qoder CN IDE)
- Entry pitfall:
bin/qoder-cn.cmd --list-extensionsreports "QoderCN CLI is not installed"; in the same directory,bin/code.cmdis the extension management entry point. - Directory pitfall:
~/.qoder/extensions(80+ extensions) belongs to Qoder IDE (another product),product.json'sdataFolderName: .qoder-cnpoints to the real directory. - Interception pitfall: all 5 imported extensions were intercepted as "Built-in",
--forceafter that all were uninstalled successfully. - Residue pitfall: after uninstalling,
~/.qoder-cn/extensionsleft 17 folders (including 11.GUIDtemporary directories and 1 legacy extension); after reclaiming them according to step 4,extensions.jsonreturned to 0. - The user explicitly refused any backup files—after deletion, even the backup manifest must be reclaimed.
- Resurrection pitfall: after cleanup was completed, the user started that IDE once, and the 5 Built-in extensions were automatically re-delivered (with renewed version numbers). User ruling: such automatic built-in items are exempt and not handled (see "Exemption clause").
Real-world case 2 (2026-08-31, Qoder IDE)
- Entry:
bin/code.cmdmanages extensions (78 items),bin/qoder.cmdis an agent CLI shell—isomorphic to case 1. - New pitfall 1: when the IDE process was running, batch uninstalling caused 3 failures (1 dependency blockage + 2 phantom
not installed); after the process exited, retrying succeeded.Lesson: check processes before acting (iron rule 6). - New pitfall 2:
ms-python.pythonwas blocked by the built-in Pylance dependency, but Pylance is not in the user registry (--uninstallreported not installed); after the IDE was closed, directly retryingms-python.python --forcesucceeded. - Note:
%APPDATA%\Qoder\Usercontains Qoder's ownmcp.json、app.jsonetc., not part of the VSCode trio, left untouched during reset. - Four-evidence closed loop passed: list empty / directory only has
extensions.json/ settings{}/ keybindings[], registry count 0.
Practical case 3 (2026-08-31, Trae EN)
- Entry:
bin/trae.cmdthe only CLI,--list-extensionsavailable (122 items). - Attribution:
dataFolderName: .trae; same family includes.trae-cn/.trae-aiccand%APPDATA%\Trae CN/TRAE SOLO CN, only touch~/.trae/extensionsand%APPDATA%\Trae\User。 - New pitfall (Iron Rule 9 triggered for the first time):
--uninstall-extensionforall 122 extensions report the same errorCannot read properties of undefined (reading 'isProtectedExtension'), with or without--forceit's the same—the fork broke the CLI uninstall path. Retrying one by one is a dead end. - Solution: use the "direct registry modification approach"—first confirm the
extensions/directory has notrae.*/cloudide.*protected files (the source whitelist istrae.aiand 3 other items, none of which are in the directory), thenextensions.jsonwrite[], reclaim 149 physical directories, and reset the configuration trio. - Note:
~/.traealso containsagent-extensions/、rules/、skills/and other Trae agent layers, only touch theextensions/subdirectory. - Four-evidence closed loop passed: list empty (exit 0) / directory only has
extensions.json/ settings{}/ keybindings[], registry count 0.
Practical case 4 (2026-08-31, Trae CN)
- Path mix-up (the direct cause of the newly added fifth check): first obtained
D:\dev-tool\ai-ide\trae-cn(empty shell, an empty directory created on 2026-02-14), almost handled it as "residual cleanup"; after the user corrected it, confirmed the real body is inD:\dev-tool\ai-agent\trae-code-cn(214MB main program).Lesson: a directory with no exe / no product.json is an empty shell, the path must be verified word by word (§0 check 5). - Attribution:
dataFolderName: .trae-cn,nameLong: Trae CN; entrybin/trae-cn.cmdonly. - Plugin layer is already in factory state:
--list-extensionsempty, registry[], no settings.json / keybindings.json, snippets empty—use the "already in factory state branch", do not force finding work. - Family prediction correction: Trae EN's CLI uninstall is completely broken, but Trae CN's
--uninstall-extensionis completely normal (single-item retest passed)—same family ≠ same disease, predictions must be confirmed by retesting. - User decision: only clear the cache layer—reclaim
%APPDATA%\Trae CN\User\underHistory//globalStorage//workspaceStorage/;~/.trae-cn(134M, including builtin/plugins/jwt tokens) and%APPDATA%\Trae CNtop-level Electron cache (CachedData 100M etc.)keep, list the items for the user, do not act without approval.
Practical case 5 (2026-08-31, CodeBuddy CN)
- Same type as case 4:
buddycn.cmdCLI normal, plugin layer factory state out of the box (list empty / registry[]), no keybindings, snippets empty—use the "already in factory state branch". - New exemption identification:
settings.jsononly 14 lines and all areCodeBuddy.*/codingcopilot.*prefix—this is the fork's own AI configuration, not imported editor configuration, keep as exempt.Identification method: check the configuration prefix line by line, if all are the fork's own namespace then exempt; only wheneditor.*/workbench.*and other VSCode general items are mixed in is it imported configuration. - User decision as usual clears the cache layer: reclaim
%APPDATA%\CodeBuddy CN\User\under three cache directories (about 2MB total); same family.codebuddy(international version) untouched.
Practical case 6/7 (2026-08-31, Kiro + Antigravity, dual-target parallel)
- Both target structures are standard VSCode forks (exe + product.json + bin),
kiro.cmd(46 items) andantigravity.cmd(79 items) CLI uninstall paths are both normal,two-way background parallel uninstallis the standard posture for batch targets. - Antigravity 2
ms-vscode.remote-*reportednot installedphantoms (Iron Rule 5 skip); its CLI prints[createInstance] ... antigravityAnalytics NOT registeredstderr warning on every invocation—harmless noise, but it pollutes the pipeline exit code (see §6 verification discipline reinforcement). - Mixed-config discrimination reinforcement: Kiro's
settings.jsonis a hybrid (kiroAgent.*own items +editor.*/git.*/cSpell.*import traces mixed together). Discrimination method upgraded:as long as anyeditor.*/workbench.*/git.*and other VSCode generic items are mixed in, reset the whole thing as an imported config(under factory-restore semantics, own items will be rebuilt to default values by the IDE); only pure own prefixes are exempt (the discrimination method in case 5 applies only to pure files). - Kiro incidental risk disclosure: in the old config,
kiroAgent.trustedCommandscontained a bare wildcard"*"(equivalent to the agent command approval-free whitelist fully open), which has been eliminated after reset—proactively point out such security hazards to the user at delivery. - Boundary:
~/.kirohas an agent layer (hooks/、powers/、skills/、steering/)、~/.antigravityhas an adjacent product directory.antigravity_cockpit/.antigravity_tools/com.lbjlaq.antigravity-tools(%APPDATA%), neither was touched. - Dual-target four evidences all green: list empty (exit 0 after redirection) / directory only has
extensions.json/ settings{}/ keybindings[], both registry counts 0.