Creating Custom Skills
A custom skill is a directory with two files: a manifest and an executor.
Minimal Example
~/my-skills/
joke/
skill.json
index.jsskill.json
json
{
"name": "joke",
"description": "Tell a random programming joke",
"tools": [
{
"name": "get_joke",
"description": "Returns a random programming joke",
"parameters": {
"type": "object",
"properties": {},
"required": []
}
}
]
}index.js
js
const jokes = [
'Why do programmers prefer dark mode? Because light attracts bugs.',
'A SQL query walks into a bar, walks up to two tables and asks: Can I join you?',
]
export async function get_joke() {
return jokes[Math.floor(Math.random() * jokes.length)]
}Point Airupt at your skills directory:
yaml
skills:
custom_skills_dir: ~/my-skillsRestart Airupt and test:
Tell me a joke.Tool Parameters
Tools can accept parameters:
skill.json
json
{
"name": "weather",
"description": "Get current weather for a city",
"tools": [
{
"name": "get_weather",
"description": "Fetch current weather for a given city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, e.g. Berlin"
}
},
"required": ["city"]
}
}
]
}index.js
js
export async function get_weather({ city }) {
const res = await fetch(`https://wttr.in/${encodeURIComponent(city)}?format=3`)
return res.text()
}TypeScript Skills
TypeScript is supported. Name your file index.ts and Airupt will compile it on load:
ts
export async function get_weather({ city }: { city: string }): Promise<string> {
const res = await fetch(`https://wttr.in/${encodeURIComponent(city)}?format=3`)
return res.text()
}Skill Lifecycle
- Skills are loaded once at startup
- To reload after editing:
airupt skills reload(no full restart needed) - Errors in a skill are caught and reported; other skills continue running
Best Practices
- Keep each tool focused on one action
- Return plain strings or JSON-serialisable objects
- Use
descriptionfields thoroughly — the LLM uses them to decide when to call your tool - Avoid side effects in
skill.json; all logic goes inindex.js