fix(claude-code-command-loader): skip EXCLUDED_DIRS and memoize per directory

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-04-18 14:13:12 +09:00
parent 3cb1d5d936
commit 89d394ed3e
2 changed files with 65 additions and 2 deletions
@@ -0,0 +1,37 @@
import { promises as fs } from "fs"
import { resolve } from "path"
import type { CommandDefinition } from "./types"
const commandLoaderCache = new Map<string, Promise<Record<string, CommandDefinition>>>()
export async function getCommandLoaderCacheKey(directory?: string): Promise<string> {
const resolvedDirectory = resolve(directory ?? process.cwd())
try {
return await fs.realpath(resolvedDirectory)
} catch {
return resolvedDirectory
}
}
export function getCachedCommands(
cacheKey: string,
): Promise<Record<string, CommandDefinition>> | undefined {
return commandLoaderCache.get(cacheKey)
}
export function setCachedCommands(
cacheKey: string,
commands: Promise<Record<string, CommandDefinition>>,
): void {
commandLoaderCache.set(cacheKey, commands)
}
export function deleteCachedCommands(cacheKey: string): void {
commandLoaderCache.delete(cacheKey)
}
export function clearCommandLoaderCache(): void {
commandLoaderCache.clear()
}
@@ -4,13 +4,23 @@ import { parseFrontmatter } from "../../shared/frontmatter"
import { sanitizeModelField } from "../../shared/model-sanitizer"
import { isMarkdownFile } from "../../shared/file-utils"
import {
EXCLUDED_DIRS,
findProjectOpencodeCommandDirs,
getClaudeConfigDir,
getOpenCodeCommandDirs,
} from "../../shared"
import { log } from "../../shared/logger"
import {
clearCommandLoaderCache,
deleteCachedCommands,
getCachedCommands,
getCommandLoaderCacheKey,
setCachedCommands,
} from "./loader-cache"
import type { CommandScope, CommandDefinition, CommandFrontmatter, LoadedCommand } from "./types"
export { clearCommandLoaderCache }
async function loadCommandsFromDir(
commandsDir: string,
scope: CommandScope,
@@ -48,6 +58,7 @@ async function loadCommandsFromDir(
for (const entry of entries) {
if (entry.isDirectory()) {
if (EXCLUDED_DIRS.has(entry.name)) continue
if (entry.name.startsWith(".")) continue
const subDirPath = join(commandsDir, entry.name)
const subPrefix = prefix ? `${prefix}/${entry.name}` : entry.name
@@ -159,11 +170,26 @@ export async function loadOpencodeProjectCommands(directory?: string): Promise<R
}
export async function loadAllCommands(directory?: string): Promise<Record<string, CommandDefinition>> {
const [user, project, global, projectOpencode] = await Promise.all([
const cacheKey = await getCommandLoaderCacheKey(directory)
const cachedCommands = getCachedCommands(cacheKey)
if (cachedCommands) {
return cachedCommands
}
const loadCommandsPromise = Promise.all([
loadUserCommands(),
loadProjectCommands(directory),
loadOpencodeGlobalCommands(),
loadOpencodeProjectCommands(directory),
])
return { ...projectOpencode, ...global, ...project, ...user }
.then(([user, project, global, projectOpencode]) => {
return { ...projectOpencode, ...global, ...project, ...user }
})
.catch((error) => {
deleteCachedCommands(cacheKey)
throw error
})
setCachedCommands(cacheKey, loadCommandsPromise)
return loadCommandsPromise
}