perf(startup): parallelize command and skill loading in config-handler

- Add async versions of skill loader functions (loadUserSkillsAsync, loadProjectSkillsAsync, loadOpencodeGlobalSkillsAsync, loadOpencodeProjectSkillsAsync)
- Use Promise.all to load 8 loaders concurrently instead of sequentially
- Improves startup performance by eliminating serial I/O bottlenecks

Generated with assistance of OhMyOpenCode
This commit is contained in:
YeonGyu-Kim
2026-01-05 14:03:17 +09:00
parent 6b5a8263f9
commit fe11ba294c
2 changed files with 67 additions and 24 deletions

View File

@@ -340,6 +340,42 @@ export function loadOpencodeProjectSkills(): Record<string, CommandDefinition> {
return skillsToRecord(skills) return skillsToRecord(skills)
} }
/**
* Async version of loadUserSkills
*/
export async function loadUserSkillsAsync(): Promise<Record<string, CommandDefinition>> {
const userSkillsDir = join(getClaudeConfigDir(), "skills")
const skills = await loadSkillsFromDirAsync(userSkillsDir, "user")
return skillsToRecord(skills)
}
/**
* Async version of loadProjectSkills
*/
export async function loadProjectSkillsAsync(): Promise<Record<string, CommandDefinition>> {
const projectSkillsDir = join(process.cwd(), ".claude", "skills")
const skills = await loadSkillsFromDirAsync(projectSkillsDir, "project")
return skillsToRecord(skills)
}
/**
* Async version of loadOpencodeGlobalSkills
*/
export async function loadOpencodeGlobalSkillsAsync(): Promise<Record<string, CommandDefinition>> {
const opencodeSkillsDir = join(homedir(), ".config", "opencode", "skill")
const skills = await loadSkillsFromDirAsync(opencodeSkillsDir, "opencode")
return skillsToRecord(skills)
}
/**
* Async version of loadOpencodeProjectSkills
*/
export async function loadOpencodeProjectSkillsAsync(): Promise<Record<string, CommandDefinition>> {
const opencodeProjectDir = join(process.cwd(), ".opencode", "skill")
const skills = await loadSkillsFromDirAsync(opencodeProjectDir, "opencode-project")
return skillsToRecord(skills)
}
/** /**
* Discover all skills from all sources with priority ordering. * Discover all skills from all sources with priority ordering.
* Priority order: opencode-project > project > opencode > user * Priority order: opencode-project > project > opencode > user

View File

@@ -1,16 +1,16 @@
import { createBuiltinAgents } from "../agents"; import { createBuiltinAgents } from "../agents";
import { import {
loadUserCommands, loadUserCommandsAsync,
loadProjectCommands, loadProjectCommandsAsync,
loadOpencodeGlobalCommands, loadOpencodeGlobalCommandsAsync,
loadOpencodeProjectCommands, loadOpencodeProjectCommandsAsync,
} from "../features/claude-code-command-loader"; } from "../features/claude-code-command-loader";
import { loadBuiltinCommands } from "../features/builtin-commands"; import { loadBuiltinCommands } from "../features/builtin-commands";
import { import {
loadUserSkills, loadUserSkillsAsync,
loadProjectSkills, loadProjectSkillsAsync,
loadOpencodeGlobalSkills, loadOpencodeGlobalSkillsAsync,
loadOpencodeProjectSkills, loadOpencodeProjectSkillsAsync,
} from "../features/opencode-skill-loader"; } from "../features/opencode-skill-loader";
import { import {
loadUserAgents, loadUserAgents,
@@ -282,24 +282,31 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
}; };
const builtinCommands = loadBuiltinCommands(pluginConfig.disabled_commands); const builtinCommands = loadBuiltinCommands(pluginConfig.disabled_commands);
const userCommands = (pluginConfig.claude_code?.commands ?? true)
? loadUserCommands()
: {};
const opencodeGlobalCommands = loadOpencodeGlobalCommands();
const systemCommands = (config.command as Record<string, unknown>) ?? {}; const systemCommands = (config.command as Record<string, unknown>) ?? {};
const projectCommands = (pluginConfig.claude_code?.commands ?? true)
? loadProjectCommands()
: {};
const opencodeProjectCommands = loadOpencodeProjectCommands();
const userSkills = (pluginConfig.claude_code?.skills ?? true) // Parallel loading of all commands and skills for faster startup
? loadUserSkills() const includeClaudeCommands = pluginConfig.claude_code?.commands ?? true;
: {}; const includeClaudeSkills = pluginConfig.claude_code?.skills ?? true;
const projectSkills = (pluginConfig.claude_code?.skills ?? true)
? loadProjectSkills() const [
: {}; userCommands,
const opencodeGlobalSkills = loadOpencodeGlobalSkills(); projectCommands,
const opencodeProjectSkills = loadOpencodeProjectSkills(); opencodeGlobalCommands,
opencodeProjectCommands,
userSkills,
projectSkills,
opencodeGlobalSkills,
opencodeProjectSkills,
] = await Promise.all([
includeClaudeCommands ? loadUserCommandsAsync() : Promise.resolve({}),
includeClaudeCommands ? loadProjectCommandsAsync() : Promise.resolve({}),
loadOpencodeGlobalCommandsAsync(),
loadOpencodeProjectCommandsAsync(),
includeClaudeSkills ? loadUserSkillsAsync() : Promise.resolve({}),
includeClaudeSkills ? loadProjectSkillsAsync() : Promise.resolve({}),
loadOpencodeGlobalSkillsAsync(),
loadOpencodeProjectSkillsAsync(),
]);
config.command = { config.command = {
...builtinCommands, ...builtinCommands,