skills/tool-creator/SKILL.md
Create valid, type-safe TypeScript tools for OpenCode — generates correct boilerplate, typed interfaces, and handler stubs. Use when building new tools for global config or per-project .opencode/tools/.
npx skillsauth add Thomashighbaugh/opencode tool-creatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when creating OpenCode TypeScript tools that extend the agent's capabilities. The skill interviews you about what the tool should do, generates valid boilerplate via tool-scaffolder, and validates the output.
~/.config/opencode/tools/ (global scope).opencode/tools/ (project scope)tools/ first)/skills create)opencode-command-creator)opencode-agent-creator)Ask the user these questions, one at a time:
my-utility, project-info, db-migrate)If the user says yes to parameters, collect each parameter:
Call tool-scaffolder with the collected information:
tool-scaffolder {
action: "generate",
language: "typescript" | "python" | "bash",
name: "<kebab-case-name>",
description: "<description>",
params: '[{"name":"...","type":"string","required":true,"description":"..."}]',
scope: "global" | "project"
}
The tool returns { ok: true, language: "...", path: "...", params: N, size: N }.
Call tool-scaffolder with the validate action:
tool-scaffolder {
action: "validate",
outputPath: "<path from generate step>"
}
Validation checks vary by language:
| Language | Checks |
| ---------- | ---------------------------------------------------------------------- |
| TypeScript | import, export default tool(), description, args, async execute |
| Python | shebang (#!/usr/bin/env python3), argparse, main(), __name__ guard |
| Bash | shebang (#!/usr/bin/env bash), set -euo pipefail |
If validation fails, fix the issues and re-validate.
Show the user:
TODO: implement tool logicGenerated tools follow this canonical pattern:
import { tool } from "@opencode-ai/plugin"
import * as fs from "fs"
import * as path from "path"
import { homedir } from "os"
interface MyToolArgs {
input: string
verbose?: boolean
}
export default tool({
description: "What this tool does",
args: {
input: tool.schema.string().describe("Input value"),
verbose: tool.schema.boolean().optional().describe("Enable verbose output"),
},
async execute(args: MyToolArgs, context) {
const projectRoot = context.directory || process.cwd()
// TODO: implement tool logic
return JSON.stringify({ ok: true })
},
})
#!/usr/bin/env python3
"""<description>"""
import argparse
import json
import sys
def main():
parser = argparse.ArgumentParser(description="<description>")
parser.add_argument("--input", type=str, required=True, help="Input value")
parser.add_argument("--verbose", action="store_true", help="Verbose output")
args = parser.parse_args()
# TODO: implement tool logic
result = {"ok": True}
print(json.dumps(result))
if __name__ == "__main__":
main()
#!/usr/bin/env bash
set -euo pipefail
# <description>
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--input) INPUT="$2"; shift 2 ;;
--verbose) VERBOSE=true; shift ;;
*) echo "Unknown option: $1" >&2; exit 1 ;;
esac
done
# TODO: implement tool logic
printf '{"ok": true}\n'
| Scope | TypeScript | Python / Bash | Available |
| ------- | ----------------------------------- | ----------------------------------- | ----------------- |
| global | ~/.config/opencode/tools/ | ~/.config/opencode/skills/<name>/scripts/ | All projects |
| project | <project>/.opencode/tools/ | <project>/.opencode/skills/<name>/scripts/ | This project only |
Artifact placement rule: TypeScript tools go into tools/ (global) or .opencode/tools/ (project). Python and Bash scripts go into skills/<name>/scripts/ (global) or .opencode/skills/<name>/scripts/ (project). Never create standalone scripts at the project root. See rules/artifact-placement.md.
| Type | TypeScript | Python (argparse) | Bash | Use Case |
| --------- | -------------------- | -------------------------- | ------------------- | ----------------- |
| string | tool.schema.string() | type=str | positional/flag | Text, paths, IDs |
| number | tool.schema.number() | type=float | positional/flag | Counts, limits |
| boolean | tool.schema.boolean() | action="store_true" | flag, no value | Flags, toggles |
| array | tool.schema.array() | nargs="+" | IFS-split string | Lists (of strings) |
| object | tool.schema.object() | type=json.loads | JSON string parse | Complex nested data |
After generation, always validate. The tool-scaffolder validate action checks:
TypeScript:
@opencode-ai/plugin presentexport default tool( presentdescription: field definedargs: schema definedasync execute handler presentPython:
#!/usr/bin/env python3 shebang presentimport argparse presentdef main() function presentif __name__ == "__main__" guard presentBash:
#!/usr/bin/env bash shebang presentset -euo pipefail present| BAD | GOOD |
| ---------------------------------- | ------------------------------------------- |
| Creating a tool that duplicates an existing one | Check tools/ first, then create |
| Hand-rolling boilerplate | Use tool-scaffolder generate |
| Putting tools at project root | Always in .opencode/tools/ or tools/ |
| Skipping validation | Always run tool-scaffolder validate |
| Unclear parameter descriptions | Each param gets a meaningful .describe() |
tool-scaffolder tool — the generator this skill employsopencode-command-creator skill — for slash commands instead of toolsopencode-agent-creator skill — for agents instead of toolsopencode-plugin-creator skill — for plugins instead of toolsrules/artifact-placement.md — where generated files gotesting
Explore multiple solution branches in parallel, evaluate each, and recommend the best path. Use when the user explicitly invokes /ideation tree-of-thoughts or asks for "tree of thought" / "branching exploration".
testing
Run multiple independent reasoning passes and find consensus. Use when the decision is critically important, the stakes are high, or the user explicitly requests "run it multiple times" / "check consistency" / "self-consistency".
testing
Optimization by PROmpting — generate candidate prompt variations, test each against a benchmark, and report the best performer. Use when the user invokes /ideation opro or asks for "prompt optimization" / "OPRO".
development
Scan, validate, and auto-tag global OpenCode resources (skills, agents, rules, archetypes) for resource_tags filtering. Used by /init-project, config maintenance, and by stack-recommender for accurate mapping.