Repository navigation
Conversation
Desktop boot no longer writes hooks into config dirs of agents that are not installed (binary on PATH or usual install dir, or config dir present). Re-provision on window focus (at most once a minute) so installing an agent after Paradev still gets its hooks without a restart. Stacked on #9219.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
[Medium impact] The changes affect desktop setup of local agent integrations. Fix Claude provisioning before merging; users without Claude still get its config directory and settings. FindingsFix with agent prompt### Issue 1
packages/agent-setup/src/agent-setup.ts:252-253
`skipUninstalledAgents` still creates `~/.claude` on a machine without Claude. Before this check, `createManagedSkills()` copies the bundled plugin into `~/.claude/skills/superset`. The check then treats that newly created directory as proof that Claude is installed and writes its settings and wrapper too.
Pass the installation filter into Claude plugin provisioning while keeping the shared `~/.agents` skills unchanged.
### Issue 2
packages/agent-setup/src/installed-agents.ts:84-86
The config-directory fallback ignores supported custom locations. If `KIMI_CODE_HOME` points to an existing profile and the Kimi binary is outside the desktop's search directories, this checks only `~/.kimi-code` and skips Kimi's hook setup. The existing writer correctly uses `KIMI_CODE_HOME`.
Resolve the same effective config paths here. The same mismatch affects `OMP_CODING_AGENT_DIR` and the `XDG_CONFIG_HOME` paths for Devin and Muse.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.SummaryDesktop setup now skips agents that installation detection cannot find. Window focus retries setup after onboarding, at most once per minute. Other callers keep the existing default.
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Post-onboarding setup or throttled focus] --> B[Desktop requests installed agents only]
B --> C[Provision shared skills]
C --> D[Create Claude plugin directory]
D --> E[Check agent installation]
E --> F[Claude directory now exists]
F --> G[Write Claude settings and wrapper]
E --> H[Skip other undetected agents]
Reviews (1) · Last reviewed commit: "fix(desktop): skip uninstalled agents wh..." · Reviewed by Greptile |
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
| if (skipUninstalledAgents && !isDisabled && !isInstalled(target.id)) { | ||
| continue; |
There was a problem hiding this comment.
Uninstalled Claude still gets configured
skipUninstalledAgents still creates ~/.claude on a machine without Claude. Before this check, createManagedSkills() copies the bundled plugin into ~/.claude/skills/superset. The check then treats that newly created directory as proof that Claude is installed and writes its settings and wrapper too.
Pass the installation filter into Claude plugin provisioning while keeping the shared ~/.agents skills unchanged.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/agent-setup/src/agent-setup.ts
Line: 252-253
Comment:
**Uninstalled Claude still gets configured**
`skipUninstalledAgents` still creates `~/.claude` on a machine without Claude. Before this check, `createManagedSkills()` copies the bundled plugin into `~/.claude/skills/superset`. The check then treats that newly created directory as proof that Claude is installed and writes its settings and wrapper too.
Pass the installation filter into Claude plugin provisioning while keeping the shared `~/.agents` skills unchanged.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| if (footprint.homeDirs.some((dir) => fs.existsSync(path.join(home, dir)))) { | ||
| return true; | ||
| } |
There was a problem hiding this comment.
The config-directory fallback ignores supported custom locations. If KIMI_CODE_HOME points to an existing profile and the Kimi binary is outside the desktop's search directories, this checks only ~/.kimi-code and skips Kimi's hook setup. The existing writer correctly uses KIMI_CODE_HOME.
Resolve the same effective config paths here. The same mismatch affects OMP_CODING_AGENT_DIR and the XDG_CONFIG_HOME paths for Devin and Muse.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/agent-setup/src/installed-agents.ts
Line: 84-86
Comment:
**Custom agent homes get missed**
The config-directory fallback ignores supported custom locations. If `KIMI_CODE_HOME` points to an existing profile and the Kimi binary is outside the desktop's search directories, this checks only `~/.kimi-code` and skips Kimi's hook setup. The existing writer correctly uses `KIMI_CODE_HOME`.
Resolve the same effective config paths here. The same mismatch affects `OMP_CODING_AGENT_DIR` and the `XDG_CONFIG_HOME` paths for Devin and Muse.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
9 issues found across 6 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/agent-setup/src/installed-agents.test.ts">
<violation number="1" location="packages/agent-setup/src/installed-agents.test.ts:66">
P2: This test does not verify the “only installed agent” claim for most configured agents. Expand the negative assertions to cover every agent-specific config footprint, otherwise provisioning regressions for Amp, OpenCode, OMP, Pi, MastraCode, Kimi, Vibe, Devin, or Muse can pass unnoticed.</violation>
</file>
<file name="apps/desktop/src/main/index.ts">
<violation number="1" location="apps/desktop/src/main/index.ts:260">
P2: `lastRunAt` starts at app initialization, so it consumes the one-minute cooldown before onboarding has run. If onboarding completes during that minute, the first focus afterward is skipped and a newly installed agent is not picked up until a later focus; initialize the cooldown after an actual provisioning run instead.</violation>
</file>
<file name="packages/agent-setup/src/installed-agents.ts">
<violation number="1" location="packages/agent-setup/src/installed-agents.ts:23">
P2: The shared `.gemini` directory is not Gemini-specific: Antigravity writes its hooks under `~/.gemini/config`, so an Antigravity-only install makes this check provision Gemini anyway. Use an agent-specific config marker or require a Gemini binary before treating that directory as Gemini's footprint.</violation>
<violation number="2" location="packages/agent-setup/src/installed-agents.ts:25">
P2: Resolve Kimi’s effective config home, including `KIMI_CODE_HOME`, instead of checking only `~/.kimi-code`; otherwise an existing custom profile is missed when the binary is outside the searched directories.</violation>
<violation number="3" location="packages/agent-setup/src/installed-agents.ts:29">
P2: The installation fallback ignores `XDG_CONFIG_HOME` for OpenCode, Devin, and Muse, so desktop provisioning skips installed agents whose existing config is under a custom XDG root. Resolve these footprints with the same XDG-aware paths used by their writers.</violation>
<violation number="4" location="packages/agent-setup/src/installed-agents.ts:54">
P2: This filter still treats other Superset workspace wrappers such as `~/.superset-foo/bin/claude` as real installations. The desktop gate will then provision that agent’s global config even though only Superset’s wrapper exists; exclude all Superset wrapper directory variants, not just the current `getBinDir()`.</violation>
<violation number="5" location="packages/agent-setup/src/installed-agents.ts:54">
P2: The wrapper-directory filter compares Windows paths as case-sensitive strings, so a differently cased PATH entry can expose Superset's own wrappers and mark every wrapped agent installed. Compare normalized Windows paths case-insensitively before probing binaries.</violation>
<violation number="6" location="packages/agent-setup/src/installed-agents.ts:63">
P2: `hasBinary` accepts an accessible directory named after the agent as an installed binary. Check `statSync(candidate).isFile()` before `accessSync` so a directory collision does not cause provisioning for an uninstalled agent.</violation>
</file>
<file name="packages/agent-setup/src/agent-setup.ts">
<violation number="1" location="packages/agent-setup/src/agent-setup.ts:252">
P2: Apply the installation filter to Claude plugin provisioning too; `createManagedSkills()` creates `~/.claude` before this per-target check, making the uninstalled agent appear installed and allowing its settings and wrapper to be written.</violation>
</file>
Architecture diagram
sequenceDiagram
participant DESKTOP as Desktop Main Process
participant POB as PostOnboardingSetup
participant API as agent-setup API
participant CAP as setupAgentCapabilities
participant CHECK as isAgentInstalled
participant FS as File System / PATH
participant AGENTS as Agent Config Dirs
Note over DESKTOP,AGENTS: Desktop Provisioning Flow (with skipUninstalledAgents)
DESKTOP->>DESKTOP: window focus event
DESKTOP->>POB: hasRun()
alt Not onboarded yet
POB-->>DESKTOP: false - skip reprovisioning
else Onboarded
POB-->>DESKTOP: true
DESKTOP->>DESKTOP: Check 60s throttle
DESKTOP->>API: setupAgentIntegrations({skipUninstalledAgents: true})
API->>API: Create dirs (skills, wrappers, plugins)
API->>CAP: setupAgentCapabilities(disabled, skipUninstalledAgents)
loop For each agent target
CAP->>CHECK: isAgentInstalled(agentId)
CHECK->>FS: Check HOME config dir
FS-->>CHECK: exists?
alt Config dir exists
CHECK-->>CAP: true (installed)
else No config dir
CHECK->>FS: Check PATH and binary dirs
FS-->>CHECK: binary found?
alt Binary found (not wrapper dir)
CHECK-->>CAP: true (installed)
else No binary found
CHECK-->>CAP: false (not installed)
end
end
alt Agent disabled
CAP->>AGENTS: Run teardown (even if not installed)
else Agent installed AND not skipped
CAP->>AGENTS: Run setup (write hooks/settings/plugins)
else Agent not installed AND skipUninstalledAgents
CAP->>CAP: Skip - no config dir created
end
end
API->>API: Write zsh/bash wrappers
API-->>DESKTOP: Provisioning complete
Note over DESKTOP: Managed skills (~/.agents/skills)<br/>always written after onboarding
end
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| expect(fs.existsSync(path.join(home, ".claude", "settings.json"))).toBe( | ||
| true, | ||
| ); | ||
| for (const dir of [".codex", ".cursor", ".gemini", ".grok", ".factory"]) { |
There was a problem hiding this comment.
P2: This test does not verify the “only installed agent” claim for most configured agents. Expand the negative assertions to cover every agent-specific config footprint, otherwise provisioning regressions for Amp, OpenCode, OMP, Pi, MastraCode, Kimi, Vibe, Devin, or Muse can pass unnoticed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/installed-agents.test.ts, line 66:
<comment>This test does not verify the “only installed agent” claim for most configured agents. Expand the negative assertions to cover every agent-specific config footprint, otherwise provisioning regressions for Amp, OpenCode, OMP, Pi, MastraCode, Kimi, Vibe, Devin, or Muse can pass unnoticed.</comment>
<file context>
@@ -0,0 +1,70 @@
+ expect(fs.existsSync(path.join(home, ".claude", "settings.json"))).toBe(
+ true,
+ );
+ for (const dir of [".codex", ".cursor", ".gemini", ".grok", ".factory"]) {
+ expect(fs.existsSync(path.join(home, dir))).toBe(false);
+ }
</file context>
| const AGENT_REPROVISION_MIN_INTERVAL_MS = 60_000; | ||
|
|
||
| function reprovisionAgentIntegrationsOnFocus() { | ||
| let lastRunAt = Date.now(); |
There was a problem hiding this comment.
P2: lastRunAt starts at app initialization, so it consumes the one-minute cooldown before onboarding has run. If onboarding completes during that minute, the first focus afterward is skipped and a newly installed agent is not picked up until a later focus; initialize the cooldown after an actual provisioning run instead.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/desktop/src/main/index.ts, line 260:
<comment>`lastRunAt` starts at app initialization, so it consumes the one-minute cooldown before onboarding has run. If onboarding completes during that minute, the first focus afterward is skipped and a newly installed agent is not picked up until a later focus; initialize the cooldown after an actual provisioning run instead.</comment>
<file context>
@@ -250,6 +250,24 @@ function setupAgentIntegrationsFromSettings() {
+const AGENT_REPROVISION_MIN_INTERVAL_MS = 60_000;
+
+function reprovisionAgentIntegrationsOnFocus() {
+ let lastRunAt = Date.now();
+ app.on("browser-window-focus", () => {
+ if (!postOnboardingSetup.hasRun()) return;
</file context>
| let lastRunAt = Date.now(); | |
| let lastRunAt = 0; |
| ...fromPath, | ||
| ...EXTRA_BINARY_DIRS.map((dir) => path.join(home, dir)), | ||
| ...SYSTEM_BINARY_DIRS, | ||
| ].filter((dir) => dir && path.resolve(dir) !== wrapperDir); |
There was a problem hiding this comment.
P2: This filter still treats other Superset workspace wrappers such as ~/.superset-foo/bin/claude as real installations. The desktop gate will then provision that agent’s global config even though only Superset’s wrapper exists; exclude all Superset wrapper directory variants, not just the current getBinDir().
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/installed-agents.ts, line 54:
<comment>This filter still treats other Superset workspace wrappers such as `~/.superset-foo/bin/claude` as real installations. The desktop gate will then provision that agent’s global config even though only Superset’s wrapper exists; exclude all Superset wrapper directory variants, not just the current `getBinDir()`.</comment>
<file context>
@@ -0,0 +1,88 @@
+ ...fromPath,
+ ...EXTRA_BINARY_DIRS.map((dir) => path.join(home, dir)),
+ ...SYSTEM_BINARY_DIRS,
+ ].filter((dir) => dir && path.resolve(dir) !== wrapperDir);
+}
+
</file context>
| ].filter((dir) => dir && path.resolve(dir) !== wrapperDir); | |
| ] | |
| .filter((dir) => { | |
| const resolved = path.resolve(dir); | |
| const relative = path.relative(home, resolved); | |
| return ( | |
| dir && | |
| resolved !== wrapperDir && | |
| !/^\\.superset(?:-[^/\\\\]+)?[\\/\\\\]+bin$/.test(relative) | |
| ); | |
| }); |
| dirs.some((dir) => | ||
| extensions.some((extension) => { | ||
| try { | ||
| fs.accessSync(path.join(dir, name + extension), fs.constants.X_OK); |
There was a problem hiding this comment.
P2: hasBinary accepts an accessible directory named after the agent as an installed binary. Check statSync(candidate).isFile() before accessSync so a directory collision does not cause provisioning for an uninstalled agent.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/installed-agents.ts, line 63:
<comment>`hasBinary` accepts an accessible directory named after the agent as an installed binary. Check `statSync(candidate).isFile()` before `accessSync` so a directory collision does not cause provisioning for an uninstalled agent.</comment>
<file context>
@@ -0,0 +1,88 @@
+ dirs.some((dir) =>
+ extensions.some((extension) => {
+ try {
+ fs.accessSync(path.join(dir, name + extension), fs.constants.X_OK);
+ return true;
+ } catch {
</file context>
| fs.accessSync(path.join(dir, name + extension), fs.constants.X_OK); | |
| const candidate = path.join(dir, name + extension); | |
| if (!fs.statSync(candidate).isFile()) return false; | |
| fs.accessSync(candidate, fs.constants.X_OK); |
| ...fromPath, | ||
| ...EXTRA_BINARY_DIRS.map((dir) => path.join(home, dir)), | ||
| ...SYSTEM_BINARY_DIRS, | ||
| ].filter((dir) => dir && path.resolve(dir) !== wrapperDir); |
There was a problem hiding this comment.
P2: The wrapper-directory filter compares Windows paths as case-sensitive strings, so a differently cased PATH entry can expose Superset's own wrappers and mark every wrapped agent installed. Compare normalized Windows paths case-insensitively before probing binaries.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/installed-agents.ts, line 54:
<comment>The wrapper-directory filter compares Windows paths as case-sensitive strings, so a differently cased PATH entry can expose Superset's own wrappers and mark every wrapped agent installed. Compare normalized Windows paths case-insensitively before probing binaries.</comment>
<file context>
@@ -0,0 +1,88 @@
+ ...fromPath,
+ ...EXTRA_BINARY_DIRS.map((dir) => path.join(home, dir)),
+ ...SYSTEM_BINARY_DIRS,
+ ].filter((dir) => dir && path.resolve(dir) !== wrapperDir);
+}
+
</file context>
| grok: { binaries: ["grok"], homeDirs: [".grok"] }, | ||
| copilot: { binaries: ["copilot"], homeDirs: [".copilot"] }, | ||
| vibe: { binaries: ["vibe"], homeDirs: [".vibe"] }, | ||
| devin: { binaries: ["devin"], homeDirs: [".config/devin"] }, |
There was a problem hiding this comment.
P2: The installation fallback ignores XDG_CONFIG_HOME for OpenCode, Devin, and Muse, so desktop provisioning skips installed agents whose existing config is under a custom XDG root. Resolve these footprints with the same XDG-aware paths used by their writers.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/installed-agents.ts, line 29:
<comment>The installation fallback ignores `XDG_CONFIG_HOME` for OpenCode, Devin, and Muse, so desktop provisioning skips installed agents whose existing config is under a custom XDG root. Resolve these footprints with the same XDG-aware paths used by their writers.</comment>
<file context>
@@ -0,0 +1,88 @@
+ grok: { binaries: ["grok"], homeDirs: [".grok"] },
+ copilot: { binaries: ["copilot"], homeDirs: [".copilot"] },
+ vibe: { binaries: ["vibe"], homeDirs: [".vibe"] },
+ devin: { binaries: ["devin"], homeDirs: [".config/devin"] },
+ muse: { binaries: ["muse"], homeDirs: [".config/muse"] },
+ ufo: { binaries: ["ufo"], homeDirs: [] },
</file context>
| binaries: ["cursor-agent"], | ||
| homeDirs: [".cursor"], | ||
| }, | ||
| gemini: { binaries: ["gemini"], homeDirs: [".gemini"] }, |
There was a problem hiding this comment.
P2: The shared .gemini directory is not Gemini-specific: Antigravity writes its hooks under ~/.gemini/config, so an Antigravity-only install makes this check provision Gemini anyway. Use an agent-specific config marker or require a Gemini binary before treating that directory as Gemini's footprint.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/installed-agents.ts, line 23:
<comment>The shared `.gemini` directory is not Gemini-specific: Antigravity writes its hooks under `~/.gemini/config`, so an Antigravity-only install makes this check provision Gemini anyway. Use an agent-specific config marker or require a Gemini binary before treating that directory as Gemini's footprint.</comment>
<file context>
@@ -0,0 +1,88 @@
+ binaries: ["cursor-agent"],
+ homeDirs: [".cursor"],
+ },
+ gemini: { binaries: ["gemini"], homeDirs: [".gemini"] },
+ mastracode: { binaries: ["mastracode"], homeDirs: [".mastracode"] },
+ kimi: { binaries: ["kimi"], homeDirs: [".kimi-code"] },
</file context>
| for (const target of AGENT_SETUP_TARGETS) { | ||
| const definition = AGENT_SETUP_DEFINITIONS[target.id]; | ||
| const isDisabled = disabled.has(target.id); | ||
| if (skipUninstalledAgents && !isDisabled && !isInstalled(target.id)) { |
There was a problem hiding this comment.
P2: Apply the installation filter to Claude plugin provisioning too; createManagedSkills() creates ~/.claude before this per-target check, making the uninstalled agent appear installed and allowing its settings and wrapper to be written.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/agent-setup.ts, line 252:
<comment>Apply the installation filter to Claude plugin provisioning too; `createManagedSkills()` creates `~/.claude` before this per-target check, making the uninstalled agent appear installed and allowing its settings and wrapper to be written.</comment>
<file context>
@@ -239,9 +248,13 @@ export function setupAgentCapabilities({
for (const target of AGENT_SETUP_TARGETS) {
const definition = AGENT_SETUP_DEFINITIONS[target.id];
+ const isDisabled = disabled.has(target.id);
+ if (skipUninstalledAgents && !isDisabled && !isInstalled(target.id)) {
+ continue;
+ }
</file context>
| }, | ||
| gemini: { binaries: ["gemini"], homeDirs: [".gemini"] }, | ||
| mastracode: { binaries: ["mastracode"], homeDirs: [".mastracode"] }, | ||
| kimi: { binaries: ["kimi"], homeDirs: [".kimi-code"] }, |
There was a problem hiding this comment.
P2: Resolve Kimi’s effective config home, including KIMI_CODE_HOME, instead of checking only ~/.kimi-code; otherwise an existing custom profile is missed when the binary is outside the searched directories.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/agent-setup/src/installed-agents.ts, line 25:
<comment>Resolve Kimi’s effective config home, including `KIMI_CODE_HOME`, instead of checking only `~/.kimi-code`; otherwise an existing custom profile is missed when the binary is outside the searched directories.</comment>
<file context>
@@ -0,0 +1,88 @@
+ },
+ gemini: { binaries: ["gemini"], homeDirs: [".gemini"] },
+ mastracode: { binaries: ["mastracode"], homeDirs: [".mastracode"] },
+ kimi: { binaries: ["kimi"], homeDirs: [".kimi-code"] },
+ grok: { binaries: ["grok"], homeDirs: [".grok"] },
+ copilot: { binaries: ["copilot"], homeDirs: [".copilot"] },
</file context>
What
Follow-up to #9219 for SUPER-3089. Desktop provisioning no longer writes hooks, settings or plugins into config dirs of agents the user has not installed (
~/.codex,~/.cursor,~/.gemini, ...).How
isAgentInstalledinpackages/agent-setup: an agent counts as installed when its binary is on PATH or in a usual install dir (~/.local/bin,~/.bun/bin, Homebrew, ...), or its home config dir exists. Superset's own wrapper dir is ignored.setupAgentIntegrations/setupAgentCapabilitiestakeskipUninstalledAgents. Only desktop passes it; headless/CLI/cloud hosts keep provisioning every agent, so their behavior is unchanged.Not changed
~/.agents/skills) and the zsh/bash wrappers still write after onboarding.Verification
bun testinpackages/agent-setup: newinstalled-agents.test.tspasses. Twoshell-wrappersfallback tests fail in this sandbox, and they fail the same way on fix(desktop): keep first launch quiet until the user is onboarded #9219's branch.biome checkclean;tsc --noEmitclean foragent-setup.Stacked on #9219; retarget to
mainafter it merges.Summary by cubic
Follow-up to #9219: desktop provisioning no longer writes hooks, settings, or plugins into the config dirs of agents the user hasn't installed (
~/.codex,~/.cursor,~/.gemini, ...). Headless/CLI/cloud hosts still provision all agents, so their behavior is unchanged.~/.local/bin,~/.bun/bin, ...), or no home config dir, and ignores Superset's own wrapper dir when searching.~/.agents/skills) and the zsh/bash wrappers still write after onboarding; disabled agents still get torn down whether installed or not.This PR is stacked on #9219; retarget to
mainafter it merges.Written for commit 2c6bcf5. Summary will update on new commits.