Skills

Built-in skills and create your own custom skills.

import.ts
import { commit, summarize, explain, review } from "@tryhamster/gerbil/skills";
// Vision skills
import { describeImage, analyzeScreenshot, extractFromImage } from "@tryhamster/gerbil/skills";

Built-in Skills

commit

Generate commit messages from git diffs.

commit.ts
import { commit } from "@tryhamster/gerbil/skills";
// Generate from staged changes
const msg = await commit();
// With options
const msg = await commit({
type: "conventional", // "conventional" | "simple" | "detailed"
maxLength: 72,
});
// From custom diff
const msg = await commit({ diff: myDiff });

CLI:

Terminal
gerbil commit --type conventional

summarize

Summarize documents, articles, or any content.

summarize.ts
import { summarize } from "@tryhamster/gerbil/skills";
const summary = await summarize({ content: document });
// With options
const 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.

explain.ts
import { explain } from "@tryhamster/gerbil/skills";
const explanation = await explain({ content: code });
// With options
const explanation = await explain({
content: code,
level: "beginner", // "beginner" | "intermediate" | "expert"
language: "typescript",
});

review

Code review with focus areas.

review.ts
import { review } from "@tryhamster/gerbil/skills";
const feedback = await review({ code });
// With options
const feedback = await review({
code,
focus: ["security", "performance", "style", "bugs"],
format: "detailed", // "inline" | "summary" | "detailed"
});

Other Built-in Skills

other-skills.ts
import { test, translate, extract, title } from "@tryhamster/gerbil/skills";
// Generate tests
const tests = await test({
code,
framework: "vitest", // "jest" | "vitest" | "mocha" | "playwright"
style: "unit",
});
// Translate
const spanish = await translate({ text, to: "es" });
// Extract structured data
const data = await extract({
content: pdfText,
schema: invoiceSchema, // Zod schema
});
// Generate title
const 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.

describe-image.ts
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.

analyze-screenshot.ts
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.

extract-from-image.ts
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.

compare-images.ts
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.

caption-image.ts
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

skills/sentiment.skill.ts
01// skills/sentiment.skill.ts
02import { 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 Zod
11 input: z.object({
12 text: z.string(),
13 detailed: z.boolean().default(false),
14 }),
15
16 // Output schema for structured output
17 output: z.object({
18 sentiment: z.enum(["positive", "negative", "neutral"]),
19 confidence: z.number(),
20 }),
21
22 // Skill settings
23 temperature: 0.3,
24
25 // Implementation
26 async run({ input, gerbil }) {
27 return gerbil.json(
28 `Analyze the sentiment: ${input.text}`,
29 { schema: this.output }
30 );
31 },
32});

Load Custom Skills

use-custom.ts
import { loadSkills, useSkill } from "@tryhamster/gerbil/skills";
// Load all skills from a directory
await loadSkills("./skills");
// Use by name
const sentiment = useSkill("sentiment");
const result = await sentiment({ text: "I love this product!" });
console.log(result);
// { sentiment: "positive", confidence: 0.95 }

Direct Import

direct-import.ts
// Import skill directly
import sentimentSkill from "./skills/sentiment.skill.js";
const result = await sentimentSkill({ text: "Hello world" });

Skill API

SkillDefinition

SkillDefinition.ts
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

SkillContext.ts
interface SkillContext<TInput> {
input: TInput; // Validated input
gerbil: Gerbil; // Gerbil instance (loaded and ready)
rawInput: unknown; // Raw input before validation
}

Registry Functions

registry.ts
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 skills
console.log(listSkills());
// ["commit", "summarize", "explain", "review", "sentiment", ...]
// Get skill info
const info = getSkillInfo("sentiment");
console.log(info.description);

CLI Usage

Terminal
# Built-in skills
gerbil commit
gerbil summarize README.md --length short
gerbil explain src/index.ts --level beginner
gerbil review src/ --focus security
# Use custom skill from file
gerbil skill ./skills/sentiment.skill.ts --text "Great product!"
# Use skill from directory
gerbil skill sentiment --skills-dir ./skills --text "Hello"
# List all skills
gerbil skills
gerbil skills --dir ./skills
# Skill info
gerbil skills info sentiment

Example Skills

Email Writer

skills/email.skill.ts
// skills/email.skill.ts
import { 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.ts
// skills/sql.skill.ts
import { 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):

Terminal
chat, skills, tools, model, integrate, benchmark, info, serve,
repl, generate, models, bench, help, version, gerbil

Sharing Skills

Skills are just TypeScript files. Share them by:

  • Copying the .skill.ts file
  • Publishing as an npm package
  • Sharing on GitHub
npm-skills.ts
// Load from npm package (future)
import { loadSkillPackage } from "@tryhamster/gerbil/skills";
await loadSkillPackage("gerbil-skills-extra");