Guide
Write your
own manifest
A manifest is a single JSON file that tells AI agents what your CLI does, when to use it, and how to call it. This guide walks through every required field and the small habits that make a manifest discoverable.
01The four questions
Every manifest answers four questions. If you can answer these in a paragraph, you can write a manifest.
| Question | Field | Format |
|---|---|---|
| What does it do? | description | 10–200 chars, plain English |
| When should the agent reach for it? | intent_triggers | ≥ 5 phrases, mixed languages |
| What inputs does it need? | input_schema | JSON Schema-style |
| What does it return? | output_schema | json / csv / text |
02Pick a category
Place the manifest under the right folder. There are 10 categories — pick the closest fit.
ai-ml— model inference, embeddings, transcription, OCRdata— SQL, CSV, ETL, schema introspectiondevops— Docker, git, CI/CD, code analysis, lintmedia— video, image, audio processingweb— HTTP, scraping, API utilitiessecurity— scanning, audit, encryptionproductivity— files, text conversion, document toolsfinance— market data, invoices, ledgersscience— units, statistics, computationnetworking— DNS, IP, packet diagnostics
03The full template
Save this as manifests/<category>/<your-tool>.json and edit the fields.
{
"name": "video-to-gif",
"version": "1.0.0",
"category": "media",
"description": "Convert a video file to an animated GIF with configurable framerate and resolution",
"intent_triggers": [
"convert mp4 to gif",
"turn this video into a gif",
"make a short looping animation from this clip",
"export the first 5 seconds of a video as a gif",
"reduce framerate when generating gif",
"把影片轉成 GIF",
"幫我把這段影片做成 gif 動圖"
],
"input_schema": {
"input": { "type": "string", "required": true, "description": "Path to the source video file" },
"output": { "type": "string", "required": true, "description": "Path to write the output GIF" },
"fps": { "type": "integer", "required": false, "default": 15 },
"width": { "type": "integer", "required": false }
},
"output_schema": {
"format": "json",
"fields": ["output_path", "frame_count", "file_size_bytes"]
},
"examples": [
{
"query": "convert demo.mp4 to a 10-fps gif",
"params": { "input": "demo.mp4", "output": "demo.gif", "fps": 10 }
}
],
"error_codes": {
"1": "Input file not found",
"2": "ffmpeg not installed"
},
"tags": ["video", "gif", "ffmpeg"]
}
04Write good intent_triggers
This is the field that decides whether the router finds your tool. Spend time here.
Rules
- ≥ 5 entries, ideally 7–10. More is better up to a point.
- Mix languages. At least 2 entries in each major language your users speak. Chinese + English is the floor.
- Vary the phrasing style. Imperative, declarative, casual — all of them.
- Cover edge cases. Mention interesting parameters in some triggers.
- No near-duplicates. "convert video to gif" + "change video to gif" wastes a slot.
The router embeds each trigger and uses them for retrieval. Diverse triggers create a fuller semantic region for your tool, making it discoverable from different ways of asking.
Anti-patterns
- ✗ All five triggers are minor variations of the same sentence
- ✗ Single language only
- ✗ Triggers that overlap heavily with another tool
- ✗ Trap words. If your tool is
format-fix, don't include "lint"
05Write at least one example
An example is a (query, params) pair the router uses as a template.
{
"query": "convert demo.mp4 to a 10-fps gif",
"params": { "input": "demo.mp4", "output": "demo.gif", "fps": 10 }
}
When an agent's intent is similar enough (cosine ≥ 0.85), the router fills your example's
params directly without calling an LLM. This is "Path A" — zero LLM tokens.
Each example covers a different use shape (default params, common override, edge case). More examples = more A-path hits = lower agent cost.
06Validate locally
Two-step check: schema first, routing second.
# Install
pip install clibrary-hub
# 1. Schema check — does your manifest meet the format rules?
python -c "from clibrary_hub import validator; r = validator.validate_file('manifests/media/your-tool.json'); print(r); [print(' ERROR:', e) for e in r.errors]; [print(' WARN: ', w) for w in r.warnings]"
# 2. Build FAISS indices including your new manifest
clibrary-build-index --manifest-dir ./manifests
# 3. Routing check — does the router actually pick your tool?
python -c "from clibrary_hub import router; print(router.route('make a gif from demo.mp4'))"
Required fields, name kebab-case, semver version, allowed category, description length 10–200, ≥ 5 intent_triggers (warns if single-language), input_schema types, output_schema.format, examples structure, and error_codes. Runs entirely offline.
If the router doesn't pick your tool for an obvious intent (after schema passes), your intent_triggers probably need more variety or stronger keyword anchors.
07Open a PR
- Fork clibrary-hub/cli-tools
- Create a branch, commit your manifest under the right category folder
- Open a PR. Briefly explain what the tool does and why an agent would want it
- The CI validates schema and checks for duplicate names
Common mistakes
| Mistake | Fix |
|---|---|
| Description longer than 200 chars or marketing-speak | One sentence, plain. State what it does, not why it's good. |
| Only English triggers | Add at least 2 entries in any other language your users use. |
Examples without working params | Run the example yourself before submitting. |
Generic error_codes ("1: error") | Be specific. "1": "Input file not found". |
If your tool doesn't actually return frame_count, don't put it in output_schema.fields. The agent will trust it.