@jeremiewerner/motto
v0.0.7
Published
Framework for authoring, validating, and packaging Claude Code Agent Skills
Maintainers
Readme
Motto
Framework for authoring, validating, and packaging Claude Code Agent Skills
Motto is a framework for authoring, validating, and packaging Claude Code Agent Skills. You write skills as structured SKILL.md files in a source tree, Motto's strict linter enforces a schema before anything ships, and motto build packages them into a self-contained, distributable plugin. The built output is plain, standard Agent Skills — any agent loads them with no knowledge of Motto.
The core value is the strict schema + linter: skills either conform or they don't, and you know before they ship.
Contents
- Install the CLI
- Scaffold a project
- Author a skill
- Validate and build
- Ship your plugin
- Publish to npm
- End-to-end example
- Add the marketplace to Claude Code
- Install Motto's skills
- Claude Desktop usage
- Development and contributing
Install the CLI
npm i -g @jeremiewerner/mottoOnce installed, the CLI is available as motto:
motto init # scaffold a skills project in the current directory
motto lint [path] # validate all skills and the project config
motto build [path] # lint, then wipe and rebuild dist/Run motto --help (or -h) at any time to print full usage.
Scaffold a project
mkdir my-project && cd my-project
motto init my-projectmotto init [name] scaffolds the current directory — [name] is optional and defaults to the directory's own name. It writes a complete, immediately-buildable skills project:
my-project/
skills/
hello-world/
SKILL.md ← starter skill; replace with your own
shared/
references/ ← shared references bundled into multiple skills at build time
motto.yaml ← project configuration
.gitignore
.claude-plugin/
marketplace.json ← points Claude Code's /plugin marketplace add at dist/public/
dist/ ← generated by `motto build`; never edit manuallyThe scaffolded motto.yaml:
name: my-project
version: "0.1.0"
description: A skills project scaffolded by motto init.
plugins:
public: my-project| Field | Required | Rule |
|-------|----------|------|
| name | Yes | Truthy string; project identifier |
| version | Yes | Truthy string; recommend quoting to preserve as YAML string |
| description | Yes | Truthy string; feeds into each built plugin.json |
| plugins.public | Yes | Letter-start kebab-case (Claude Code plugin name requirement — no reserved-word restriction, unlike skill name) |
| plugins.private | When private skills exist | Same kebab-case rule |
Two guards protect the scaffold:
- Name:
[name](or the directory name it defaults to) must be letter-start kebab-case — the same rulemotto lintenforces on skill names. --force: letsmotto initwrite into a non-empty directory. It never deletes files, but the five scaffold paths (motto.yaml,.gitignore,skills/hello-world/SKILL.md,shared/references/.gitkeep,.claude-plugin/marketplace.json) are overwritten if they already exist.
Author a skill
Hand the /motto:build-skill skill in Claude Code any input — pasted text, a document, or a conversation transcript. It extracts what's already given and asks about genuinely-missing schema slots in one batched message, auto-detects whether the skill needs template: procedure, writes skills/<name>/SKILL.md (plus any declared output-template files), runs the real motto lint in a loop (up to 3 self-fixing attempts), self-reviews against a content-quality gate, then reports back with a compact receipt.
Every SKILL.md requires three frontmatter fields and a body spine — an H1 title line plus a non-empty <role>…</role> section:
---
name: my-skill # letter-start kebab-case; must match the folder name
description: What this skill does and when an agent should trigger it.
audience: public # public → dist/public/; private → dist/private/
---
# My Skill
<role>
You are a guide who walks the author through X step by step.
</role>name— letter-start kebab-case; must equal the folder name exactly.description— non-empty, under 1024 characters, no XML tags; tells the agent what to do and when.audience—publicorprivate; routes the skill to the correct plugin bucket.- Body spine: first non-blank line is an H1 title; body contains a non-empty
<role>...</role>section.
Run motto lint at any time to see all errors in one pass.
Validate and build
motto lint [path]Reports every schema violation across all skills and the project config in a single run. Defaults to the current directory when [path] is omitted. Clean output:
✓ 2 skills OKmotto build [path]Runs motto lint first. If lint fails, nothing is written to dist/. On success, dist/ is wiped and rebuilt:
dist/
public/
.claude-plugin/
plugin.json ← { "name": "motto", "version": "...", "description": "..." }
build-skill/
SKILL.md
references/
skill-schema.md
private/
.claude-plugin/
plugin.json
secret-skill/
SKILL.mdShip your plugin
Once motto build succeeds, commit dist/public/ and push your repository to a public host — motto init already created .claude-plugin/marketplace.json pointing at ./dist/public/, so there's nothing left to configure.
Consumers then add your marketplace and install your plugin:
/plugin marketplace add <owner>/<repo>
/plugin install <plugin>@<marketplace>Prerequisite: substitute
<owner>/<repo>with your own public GitHub repository, and<plugin>with theplugins.publicname from yourmotto.yaml.<marketplace>is thenamefield of the scaffolded.claude-plugin/marketplace.json—motto initsets it to your project name, so for a project namedmy-projectthe install command is/plugin install my-project@my-project.
Publish to npm
The release skill at skills/release/SKILL.md carries the full maintainer checklist. The short version:
node --test # all tests must pass first
npm version X.Y.Z -m "chore: release v%s" # bumps package.json + motto.yaml, creates tag
node bin/motto.js lint && node bin/motto.js build # local dogfood sanity check
git push --follow-tags # hand off to CIPublishing itself happens in CI, not locally. Pushing the tag triggers a GitHub Actions run that re-runs the full test suite against the tagged commit, then publishes to npm via OIDC trusted publishing (no NPM_TOKEN involved) and creates the matching GitHub Release. See skills/release/SKILL.md for the full runbook, including how to verify CI actually published and how to recover if it doesn't.
End-to-end example
A complete flow from scaffold to install, showing shell commands and Claude Code slash commands side by side:
# 1 — Install the CLI
npm i -g @jeremiewerner/motto# 2 — Scaffold a new project (CLI)
mkdir my-project && cd my-project
motto init my-project# 3 — Author your first skill (Claude Code slash command)
/motto:build-skill# 4 — Validate all skills
motto lint# 5 — Build the plugin
motto build
# → dist/public/ is populated (dist/private/ appears only once you add audience: private skills)6 — Ship it: commit dist/public/ and push your repository to a public host — see Ship your plugin.
# 7 — Add your marketplace to Claude Code (Claude Code slash command)
/plugin marketplace add <owner>/<repo># 8 — Install your public skills into Claude Code (Claude Code slash command)
/plugin install <plugin>@<marketplace>
# → your project's skills (e.g. /my-project:hello-world) are now availableAdd the marketplace to Claude Code
Prerequisite: the
jeremiewerner/mottorepository must be public for the GitHub-form add to resolve.
Note: Claude Code caches installed plugin content locally, so an already-installed plugin can appear stale — not reflecting the latest published npm version — until the plugin cache is refreshed. If a skill you expect to see is missing or outdated, run
claude plugin update motto@motto(or uninstall and reinstall the plugin) to re-pull the current published tarball, then restart Claude Code to apply it.
/plugin marketplace add jeremiewerner/mottoThis registers Motto's self-hosted marketplace in Claude Code. The marketplace entry points to @jeremiewerner/motto on npm and exposes the public skills from dist/public/.
Install Motto's skills
/plugin install motto@mottoThis installs Motto's public skills into Claude Code, making the following slash commands available:
| Skill | Slash command | What it does |
|-------|--------------|-------------|
| build-skill | /motto:build-skill | Structures freeform input — pasted text, a document, or a transcript — into a conforming, lint-clean skill |
Claude Desktop usage
Claude Desktop's Code tab is Claude Code — the marketplace path above (/plugin install motto@motto) already covers it.
The symlink and zip one-liners below are for Claude Desktop Chat and other tools that accept a skill folder or a zip upload.
Symlink a built skill into the personal skills directory:
ln -s "$(pwd)/dist/public/build-skill" ~/.claude/skills/build-skillThe absolute source path ($(pwd)/dist/public/build-skill) is required so the symlink resolves correctly from ~/.claude/skills/.
Package a built skill as a zip for web upload:
cd dist/public && zip -r build-skill.zip build-skill/Both commands operate on the built output under dist/public/ (produced by motto build). Substitute build-skill with any other skill name from dist/public/ as needed.
Development and contributing
Node >= 20 is required.
npm install # install the single runtime dependency (yaml)
node --test # run the full test suite
node bin/motto.js lint # dogfood lint against the source skill tree
node bin/motto.js build # dogfood buildA full CONTRIBUTING.md (PR process, branching, CI) is planned for a future release. For now: run node --test and motto lint before submitting changes.
MIT License © Jérémie Werner
