feat(builtin-skills): add playwright skill with MCP config and disabled_skills option

- Add playwright as builtin skill with MCP server configuration
- Add disabled_skills config option to disable specific builtin skills
- Update BuiltinSkill type to include mcpConfig field
- Update skill merger to handle mcpConfig from builtin to loaded skills
- Merge disabled_skills config and filter unavailable builtin skills at plugin init
- Update README with Built-in Skills documentation
- Regenerate JSON schema

🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-01-02 00:01:44 +09:00
parent bd05f5b434
commit b0c39e222a
7 changed files with 62 additions and 4 deletions

View File

@@ -846,6 +846,22 @@ Or disable via `disabled_agents` in `~/.config/opencode/oh-my-opencode.json` or
Available agents: `oracle`, `librarian`, `explore`, `frontend-ui-ux-engineer`, `document-writer`, `multimodal-looker`
### Built-in Skills
Oh My OpenCode includes built-in skills that provide additional capabilities:
- **playwright**: Browser automation with Playwright MCP. Use for web scraping, testing, screenshots, and browser interactions.
Disable built-in skills via `disabled_skills` in `~/.config/opencode/oh-my-opencode.json` or `.opencode/oh-my-opencode.json`:
```json
{
"disabled_skills": ["playwright"]
}
```
Available built-in skills: `playwright`
### Sisyphus Agent
When enabled (default), Sisyphus provides a powerful orchestrator with optional specialized agents:

View File

@@ -34,6 +34,15 @@
]
}
},
"disabled_skills": {
"type": "array",
"items": {
"type": "string",
"enum": [
"playwright"
]
}
},
"disabled_hooks": {
"type": "array",
"items": {

View File

@@ -26,6 +26,10 @@ export const BuiltinAgentNameSchema = z.enum([
"multimodal-looker",
])
export const BuiltinSkillNameSchema = z.enum([
"playwright",
])
export const OverridableAgentNameSchema = z.enum([
"build",
"plan",
@@ -231,6 +235,7 @@ export const OhMyOpenCodeConfigSchema = z.object({
$schema: z.string().optional(),
disabled_mcps: z.array(McpNameSchema).optional(),
disabled_agents: z.array(BuiltinAgentNameSchema).optional(),
disabled_skills: z.array(BuiltinSkillNameSchema).optional(),
disabled_hooks: z.array(HookNameSchema).optional(),
disabled_commands: z.array(BuiltinCommandNameSchema).optional(),
agents: AgentOverridesSchema.optional(),
@@ -250,6 +255,7 @@ export type AgentOverrides = z.infer<typeof AgentOverridesSchema>
export type AgentName = z.infer<typeof AgentNameSchema>
export type HookName = z.infer<typeof HookNameSchema>
export type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema>
export type BuiltinSkillName = z.infer<typeof BuiltinSkillNameSchema>
export type SisyphusAgentConfig = z.infer<typeof SisyphusAgentConfigSchema>
export type CommentCheckerConfig = z.infer<typeof CommentCheckerConfigSchema>
export type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema>

View File

@@ -1,5 +1,19 @@
import type { BuiltinSkill } from "./types"
export function createBuiltinSkills(): BuiltinSkill[] {
return []
const playwrightSkill: BuiltinSkill = {
name: "playwright",
description: "Browser automation with Playwright MCP. Use for web scraping, testing, screenshots, and browser interactions.",
template: `# Playwright Browser Automation
This skill provides browser automation capabilities via the Playwright MCP server.`,
mcpConfig: {
playwright: {
command: "npx",
args: ["@playwright/mcp@latest"],
},
},
}
export function createBuiltinSkills(): BuiltinSkill[] {
return [playwrightSkill]
}

View File

@@ -1,3 +1,5 @@
import type { SkillMcpConfig } from "../skill-mcp-manager/types"
export interface BuiltinSkill {
name: string
description: string
@@ -10,4 +12,5 @@ export interface BuiltinSkill {
model?: string
subtask?: boolean
argumentHint?: string
mcpConfig?: SkillMcpConfig
}

View File

@@ -21,7 +21,7 @@ const SCOPE_PRIORITY: Record<SkillScope, number> = {
function builtinToLoaded(builtin: BuiltinSkill): LoadedSkill {
const definition: CommandDefinition = {
name: builtin.name,
description: `(builtin - Skill) ${builtin.description}`,
description: `(opencode - Skill) ${builtin.description}`,
template: builtin.template,
model: builtin.model,
agent: builtin.agent,
@@ -37,6 +37,7 @@ function builtinToLoaded(builtin: BuiltinSkill): LoadedSkill {
compatibility: builtin.compatibility,
metadata: builtin.metadata as Record<string, string> | undefined,
allowedTools: builtin.allowedTools,
mcpConfig: builtin.mcpConfig,
}
}

View File

@@ -128,6 +128,12 @@ function mergeConfigs(
...(override.disabled_commands ?? []),
]),
],
disabled_skills: [
...new Set([
...(base.disabled_skills ?? []),
...(override.disabled_skills ?? []),
]),
],
claude_code: deepMerge(base.claude_code, override.claude_code),
};
}
@@ -283,7 +289,10 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const callOmoAgent = createCallOmoAgent(ctx, backgroundManager);
const lookAt = createLookAt(ctx);
const builtinSkills = createBuiltinSkills();
const disabledSkills = new Set(pluginConfig.disabled_skills ?? []);
const builtinSkills = createBuiltinSkills().filter(
(skill) => !disabledSkills.has(skill.name as any)
);
const includeClaudeSkills = pluginConfig.claude_code?.skills !== false;
const mergedSkills = mergeSkills(
builtinSkills,