From 76698ed2963555d4b6f4e996422f1f5c580e7f86 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 20 Jan 2026 15:56:52 +0000 Subject: [PATCH] fix: allow custom skill config bag Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com> --- CHANGELOG.md | 1 + docs/tools/skills.md | 5 ++ .../config.skills-entries-config.test.ts | 46 +++++++++++++++++++ src/config/types.skills.ts | 2 +- src/config/zod-schema.ts | 1 + 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/config/config.skills-entries-config.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index b785c2ee8..25eb4769d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ Docs: https://docs.clawd.bot - TUI: show generic empty-state text for searchable pickers. (#1201) — thanks @vignesh07. - Doctor: canonicalize legacy session keys in session stores to prevent stale metadata. (#1169) - CLI: centralize CLI command registration to keep fast-path routing and program wiring in sync. (#1207) — thanks @gumadeiras. +- Config: allow custom fields under `skills.entries..config` for skill credentials/config. (#1226) — thanks @VACInc. (fixes #1225) ## 2026.1.18-5 diff --git a/docs/tools/skills.md b/docs/tools/skills.md index 2a5838af5..770f8066f 100644 --- a/docs/tools/skills.md +++ b/docs/tools/skills.md @@ -155,6 +155,10 @@ Bundled/managed skills can be toggled and supplied with env values: apiKey: "GEMINI_KEY_HERE", env: { GEMINI_API_KEY: "GEMINI_KEY_HERE" + }, + config: { + endpoint: "https://example.invalid", + model: "nano-pro" } }, peekaboo: { enabled: true }, @@ -173,6 +177,7 @@ Rules: - `enabled: false` disables the skill even if it’s bundled/installed. - `env`: injected **only if** the variable isn’t already set in the process. - `apiKey`: convenience for skills that declare `metadata.clawdbot.primaryEnv`. +- `config`: optional bag for custom per-skill fields; custom keys must live here. - `allowBundled`: optional allowlist for **bundled** skills only. If set, only bundled skills in the list are eligible (managed/workspace skills unaffected). diff --git a/src/config/config.skills-entries-config.test.ts b/src/config/config.skills-entries-config.test.ts new file mode 100644 index 000000000..1109315a2 --- /dev/null +++ b/src/config/config.skills-entries-config.test.ts @@ -0,0 +1,46 @@ +import { describe, expect, it } from "vitest"; + +import { ClawdbotSchema } from "./zod-schema.js"; + +describe("skills entries config schema", () => { + it("accepts custom fields under config", () => { + const res = ClawdbotSchema.safeParse({ + skills: { + entries: { + "custom-skill": { + enabled: true, + config: { + url: "https://example.invalid", + token: "abc123", + }, + }, + }, + }, + }); + + expect(res.success).toBe(true); + }); + + it("rejects unknown top-level fields", () => { + const res = ClawdbotSchema.safeParse({ + skills: { + entries: { + "custom-skill": { + url: "https://example.invalid", + }, + }, + }, + }); + + expect(res.success).toBe(false); + if (res.success) return; + + expect( + res.error.issues.some( + (issue) => + issue.path.join(".") === "skills.entries.custom-skill" && + issue.message.toLowerCase().includes("unrecognized"), + ), + ).toBe(true); + }); +}); diff --git a/src/config/types.skills.ts b/src/config/types.skills.ts index 26e6d28e4..362c05fec 100644 --- a/src/config/types.skills.ts +++ b/src/config/types.skills.ts @@ -2,7 +2,7 @@ export type SkillConfig = { enabled?: boolean; apiKey?: string; env?: Record; - [key: string]: unknown; + config?: Record; }; export type SkillsLoadConfig = { diff --git a/src/config/zod-schema.ts b/src/config/zod-schema.ts index 285734314..dc2e7cf74 100644 --- a/src/config/zod-schema.ts +++ b/src/config/zod-schema.ts @@ -380,6 +380,7 @@ export const ClawdbotSchema = z enabled: z.boolean().optional(), apiKey: z.string().optional(), env: z.record(z.string(), z.string()).optional(), + config: z.record(z.string(), z.unknown()).optional(), }) .strict(), )