Skills
Built-in skills and create your own custom skills.
import { commit, summarize, explain, review } from "@tryhamster/gerbil/skills";// Vision skillsimport { describeImage, analyzeScreenshot, extractFromImage } from "@tryhamster/gerbil/skills";Built-in Skills
commit
Generate commit messages from git diffs.
import { commit } from "@tryhamster/gerbil/skills";
// Generate from staged changesconst msg = await commit();
// With optionsconst msg = await commit({ type: "conventional", // "conventional" | "simple" | "detailed" maxLength: 72,});
// From custom diffconst msg = await commit({ diff: myDiff });CLI:
gerbil commit --type conventionalsummarize
Summarize documents, articles, or any content.
import { summarize } from "@tryhamster/gerbil/skills";
const summary = await summarize({ content: document });
// With optionsconst summary = await summarize({ content: document, length: "short", // "short" | "medium" | "long" format: "paragraph", // "paragraph" | "bullets" focus: ["key points", "conclusions"],});explain
Explain code or concepts at different levels.
import { explain } from "@tryhamster/gerbil/skills";
const explanation = await explain({ content: code });
// With optionsconst explanation = await explain({ content: code, level: "beginner", // "beginner" | "intermediate" | "expert" language: "typescript",});review
Code review with focus areas.
import { review } from "@tryhamster/gerbil/skills";
const feedback = await review({ code });
// With optionsconst feedback = await review({ code, focus: ["security", "performance", "style", "bugs"], format: "detailed", // "inline" | "summary" | "detailed"});Other Built-in Skills
import { test, translate, extract, title } from "@tryhamster/gerbil/skills";
// Generate testsconst tests = await test({ code, framework: "vitest", // "jest" | "vitest" | "mocha" | "playwright" style: "unit",});
// Translateconst spanish = await translate({ text, to: "es" });
// Extract structured dataconst data = await extract({ content: pdfText, schema: invoiceSchema, // Zod schema});
// Generate titleconst headline = await title({ content, style: "professional", maxLength: 60,});Vision Skills
Vision skills require a vision-capable model like ministral-3b.
describeImage
Generate detailed image descriptions.
import { describeImage } from "@tryhamster/gerbil/skills";
const description = await describeImage({ image: "https://example.com/photo.jpg", focus: "details", // "general" | "details" | "text" | "objects" | "scene" format: "bullets", // "paragraph" | "bullets" | "structured"});analyzeScreenshot
Analyze UI screenshots for feedback. Great for QA and accessibility.
import { analyzeScreenshot } from "@tryhamster/gerbil/skills";
const analysis = await analyzeScreenshot({ image: screenshotDataUri, type: "accessibility", // "ui-review" | "accessibility" | "suggestions" | "qa"});// → "Missing alt text on hero image. Color contrast ratio is 3.2:1..."extractFromImage
Extract text, code, data, or tables from images.
import { extractFromImage } from "@tryhamster/gerbil/skills";
const extracted = await extractFromImage({ image: documentPhoto, extract: "text", // "text" | "data" | "code" | "table" | "diagram" outputFormat: "markdown", // "raw" | "json" | "markdown"});compareImages
Compare two images and describe differences. Useful for visual regression testing.
import { compareImages } from "@tryhamster/gerbil/skills";
const comparison = await compareImages({ image1: beforeScreenshot, image2: afterScreenshot, focus: "differences", // "differences" | "similarities" | "detailed"});// → "The header color changed from blue to green. A new banner..."captionImage
Generate alt text or captions for accessibility and SEO.
import { captionImage } from "@tryhamster/gerbil/skills";
const caption = await captionImage({ image: photo, style: "descriptive", // "concise" | "descriptive" | "creative" | "funny"});// → "A golden sunset paints the sky in warm oranges and purples..."Skills in REPL
Run and create skills in the REPL (press 2 or navigate to Skills):
- c — Create a new skill (guided wizard)
- Enter — Run selected skill
- Esc — Back to menu
Custom Skills
Create your own skills to extend Gerbil's capabilities.
Define a Skill
01// skills/sentiment.skill.ts02import { defineSkill } from "@tryhamster/gerbil/skills";03import { z } from "zod";04
05export default defineSkill({06 name: "sentiment",07 description: "Analyze sentiment of text",08 version: "1.0.0",09 10 // Input validation with Zod11 input: z.object({12 text: z.string(),13 detailed: z.boolean().default(false),14 }),15 16 // Output schema for structured output17 output: z.object({18 sentiment: z.enum(["positive", "negative", "neutral"]),19 confidence: z.number(),20 }),21 22 // Skill settings23 temperature: 0.3,24 25 // Implementation26 async run({ input, gerbil }) {27 return gerbil.json(28 `Analyze the sentiment: ${input.text}`,29 { schema: this.output }30 );31 },32});Load Custom Skills
import { loadSkills, useSkill } from "@tryhamster/gerbil/skills";
// Load all skills from a directoryawait loadSkills("./skills");
// Use by nameconst sentiment = useSkill("sentiment");const result = await sentiment({ text: "I love this product!" });
console.log(result);// { sentiment: "positive", confidence: 0.95 }Direct Import
// Import skill directlyimport sentimentSkill from "./skills/sentiment.skill.js";
const result = await sentimentSkill({ text: "Hello world" });Skill API
SkillDefinition
interface SkillDefinition<TInput, TOutput> { name: string; // Unique skill name description: string; // Human-readable description version?: string; // Semver version author?: string; // Author info input?: z.ZodType<TInput>; // Input validation schema output?: z.ZodType<TOutput>; // Output schema (for structured output) system?: string; // Default system prompt model?: string; // Default model thinking?: boolean; // Enable thinking mode temperature?: number; // Default temperature maxTokens?: number; // Default max tokens run: (ctx: SkillContext<TInput>) => Promise<TOutput | string>;}SkillContext
interface SkillContext<TInput> { input: TInput; // Validated input gerbil: Gerbil; // Gerbil instance (loaded and ready) rawInput: unknown; // Raw input before validation}Registry Functions
import { defineSkill, // Create a skill useSkill, // Get skill by name listSkills, // List all skill names getSkillInfo, // Get skill metadata loadSkills, // Load from directory loadSkill, // Load single file} from "@tryhamster/gerbil/skills";
// List available skillsconsole.log(listSkills());// ["commit", "summarize", "explain", "review", "sentiment", ...]
// Get skill infoconst info = getSkillInfo("sentiment");console.log(info.description);CLI Usage
# Built-in skillsgerbil commitgerbil summarize README.md --length shortgerbil explain src/index.ts --level beginnergerbil review src/ --focus security
# Use custom skill from filegerbil skill ./skills/sentiment.skill.ts --text "Great product!"
# Use skill from directorygerbil skill sentiment --skills-dir ./skills --text "Hello"
# List all skillsgerbil skillsgerbil skills --dir ./skills
# Skill infogerbil skills info sentimentExample Skills
Email Writer
// skills/email.skill.tsimport { defineSkill } from "@tryhamster/gerbil/skills";import { z } from "zod";
export default defineSkill({ name: "email", description: "Write professional emails", input: z.object({ to: z.string(), subject: z.string(), context: z.string(), tone: z.enum(["formal", "friendly", "brief"]).default("professional"), }), system: "You are a professional email writer. Write clear, concise emails.", async run({ input, gerbil }) { const result = await gerbil.generate( `Write an email to ${input.to} about: ${input.subject} Context: ${input.context}Tone: ${input.tone}`, { maxTokens: 300 } ); return result.text; },});SQL Generator
// skills/sql.skill.tsimport { defineSkill } from "@tryhamster/gerbil/skills";import { z } from "zod";
export default defineSkill({ name: "sql", description: "Generate SQL queries from natural language", input: z.object({ query: z.string(), schema: z.string().optional(), dialect: z.enum(["postgres", "mysql", "sqlite"]).default("postgres"), }), model: "qwen2.5-coder-0.5b", // Use code model temperature: 0.2, async run({ input, gerbil }) { let prompt = `Generate a ${input.dialect} SQL query for: ${input.query}`; if (input.schema) { prompt += `\n\nDatabase schema:\n${input.schema}`; } prompt += "\n\nOnly output the SQL query, no explanation."; const result = await gerbil.generate(prompt); return result.text; },});Reserved Names
Skills cannot use these names (reserved for CLI commands):
chat, skills, tools, model, integrate, benchmark, info, serve,repl, generate, models, bench, help, version, gerbilSharing Skills
Skills are just TypeScript files. Share them by:
- Copying the
.skill.tsfile - Publishing as an npm package
- Sharing on GitHub
// Load from npm package (future)import { loadSkillPackage } from "@tryhamster/gerbil/skills";await loadSkillPackage("gerbil-skills-extra");