feat: v2 plugin injecting manifest skills with guardrails hook and init bin for agents

This commit is contained in:
haylan committed 2026-10-14 12:05:25 +02:00
1 parent 4ce4466a97
commit c81bc91e03
6 files changed
+443

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
// Ports the pattern list of upstream skills/misc/git-guardrails-claude-code (block-dangerous-git.sh)
// to an OpenCode v2 tool hook. Opt-in via plugin options { guardrails: true }.
export type Options = { guardrails: boolean }
export function resolveOptions(options: Record<string, unknown> | undefined): Options {
const opts = options ?? {}
const guardrails = opts.guardrails ?? false
if (typeof guardrails !== "boolean") {
throw new Error(`pocock: option guardrails must be a boolean, got ${JSON.stringify(guardrails)}`)
}
return { guardrails }
}
// Same patterns as the upstream hook script (grep -E semantics), in order.
const DANGEROUS: ReadonlyArray<readonly [string, RegExp]> = [
["git push", /git push/],
["git reset --hard", /git reset --hard/],
["git clean -fd", /git clean -fd/],
["git clean -f", /git clean -f/],
["git branch -D", /git branch -D/],
["git checkout .", /git checkout \./],
["git restore .", /git restore \./],
["push --force", /push --force/],
["reset --hard", /reset --hard/],
]
export function blockedPattern(command: string): string | undefined {
for (const [pattern, re] of DANGEROUS) if (re.test(command)) return pattern
return undefined
}
export function guardrailError(command: string, pattern: string): string {
return `BLOCKED: '${command}' matches dangerous pattern '${pattern}'. The user has prevented you from doing this.`
}
/** True when a tool-hook event targets the shell tool (v2 id may be "bash" or "shell"). */
export function isShellTool(tool: string): boolean {
return tool === "bash" || tool === "shell"
}