From 8269b6f187b9e7fa2a003b2b3066ddec4edfb9c7 Mon Sep 17 00:00:00 2001 From: "phalla.doll" Date: Mon, 25 May 2026 15:48:36 +0700 Subject: [PATCH] feat(skill): add hidden frontmatter field to skills Add a hidden boolean field to skill frontmatter, mirroring the existing AgentConfig.hidden field. Skills with hidden: true are excluded from the LLM tool description (available_skills) but remain accessible via the /skills dialog and the skill tool for manual invocation. Closes #29189 --- packages/opencode/src/skill/index.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/skill/index.ts b/packages/opencode/src/skill/index.ts index c1c6d0d6f28a..c7bba271d96b 100644 --- a/packages/opencode/src/skill/index.ts +++ b/packages/opencode/src/skill/index.ts @@ -36,6 +36,7 @@ const CUSTOMIZE_OPENCODE_SKILL_DESCRIPTION = export const Info = Schema.Struct({ name: Schema.String, description: Schema.optional(Schema.String), + hidden: Schema.optional(Schema.Boolean), location: Schema.String, content: Schema.String, }) @@ -49,11 +50,12 @@ const Issue = Schema.StructWithRest( [Schema.Record(Schema.String, Schema.Unknown)], ) -function isSkillFrontmatter(data: unknown): data is { name: string; description?: string } { +function isSkillFrontmatter(data: unknown): data is { name: string; description?: string; hidden?: boolean } { return ( isRecord(data) && typeof data.name === "string" && - (data.description === undefined || typeof data.description === "string") + (data.description === undefined || typeof data.description === "string") && + (data.hidden === undefined || typeof data.hidden === "boolean") ) } @@ -135,6 +137,7 @@ const add = Effect.fnUntraced(function* (state: State, match: string, bus: Bus.I state.skills[md.data.name] = { name: md.data.name, description: md.data.description, + hidden: md.data.hidden, location: match, content: md.content, } @@ -305,7 +308,9 @@ export const layer = Layer.effect( const available = Effect.fn("Skill.available")(function* (agent?: Agent.Info) { const s = yield* InstanceState.get(state) - const list = Object.values(s.skills).toSorted((a, b) => a.name.localeCompare(b.name)) + const list = Object.values(s.skills) + .filter((skill) => skill.hidden !== true) + .toSorted((a, b) => a.name.localeCompare(b.name)) if (!agent) return list return list.filter((skill) => Permission.evaluate("skill", skill.name, agent.permission).action !== "deny") })