From 137c389ddab1227dce6753d477714e7531351edd Mon Sep 17 00:00:00 2001 From: Jian Gong Date: Wed, 26 Aug 2026 04:08:27 +0800 Subject: [PATCH] fix: avoid creating Claude agents directory when disabled An empty roster has nothing to write, and an absent agents directory has nothing to prune. Return without creating ~/.claude while preserving cleanup for existing OpenCodex-owned definitions. --- src/claude/agents-inject.ts | 9 ++++++++- tests/claude-agents-inject.test.ts | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/claude/agents-inject.ts b/src/claude/agents-inject.ts index 6b89a1e4817..d3cec47ecb8 100644 --- a/src/claude/agents-inject.ts +++ b/src/claude/agents-inject.ts @@ -218,7 +218,14 @@ function isOwnedFile(path: string): boolean { export function syncClaudeAgentDefs(defs: readonly ClaudeAgentDef[], configDir = claudeConfigDir()): string[] | null { try { const dir = join(configDir, "agents"); - mkdirSync(dir, { recursive: true }); + if (defs.length === 0) { + try { lstatSync(dir); } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") return []; + throw error; + } + } else { + mkdirSync(dir, { recursive: true }); + } const keep = new Set(defs.map(d => d.file)); for (const existing of readdirSync(dir)) { if (!existing.startsWith(OWNED_PREFIX) || !existing.endsWith(".md")) continue; diff --git a/tests/claude-agents-inject.test.ts b/tests/claude-agents-inject.test.ts index f39b7da7a75..1fa0633a583 100644 --- a/tests/claude-agents-inject.test.ts +++ b/tests/claude-agents-inject.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; +import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { buildClaudeAgentDefs, injectClaudeAgentDefs, syncClaudeAgentDefs } from "../src/claude/agents-inject"; @@ -269,6 +269,12 @@ describe("buildClaudeAgentDefs (devlog 070 + audit 071)", () => { }); describe("syncClaudeAgentDefs ownership contract (audit 071 #2/#3)", () => { + test("empty sync leaves an absent agents directory absent", () => { + const dir = tempDir(); + expect(syncClaudeAgentDefs([], dir)).toEqual([]); + expect(existsSync(join(dir, "agents"))).toBe(false); + }); + test("writes, overwrites, and prunes ONLY marker-verified ocx files", () => { const dir = tempDir(); writeFileSync(join(dir, "settings.json"), JSON.stringify({ model: "claude-ocx-native--gpt-5.6-sol" }));