Build1 publisher2 min readPublished
check_message.py turns a commit skill's format rules into exit codes 0, 1 and 2
The Agent Skills specification requires only SKILL.md. In the commit-crafter tutorial, everything countable moves into scripts/check_message.py, tested with Python's standard library and no API key.
The Engineer · Build desk

What happened
- A dev.to tutorial builds a commit-crafter Agent Skill from the MIT-licensed how-to-create-a-skill-tutorial repository, which documents the open Agent Skills specification.
- The specification requires only SKILL.md, and the scripts/ and references/ directories are conventions, holding check_message.py and a conventional-commits.md reference in the example layout.
- check_message.py validates the Conventional Commits shape, allowed types, subject length, imperative mood, blank-line separation and breaking-change footers, printing actionable violations to stderr.
- The checker uses exit codes as its protocol: 0 for valid input, 1 for a rule violation, and 2 for no input at all.
- The skill stops at showing a validated message and commits only after explicit approval, so it never changes repository history on its own.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- capability A validator with defined exit codes can run in CI or a pre-commit hook with no agent and no API key, so the rule keeps holding when the model behind the skill changes.
- constraint Activation can hinge on the description field alone, so a skill whose description omits the phrases users actually type is installed and never invoked.
- decision Anyone adopting this layout has to decide which rules are worth a script, because a rule left in SKILL.md prose has no failing test to catch a regression.
- cost The price of the split is a second artifact: the script and its tests have to stay in step with the prose every time the skill's rules move.
The workflow in SKILL.md is five numbered steps, and exactly one of them calls the skill's own code: step 4 runs `python scripts/check_message.py --file message.txt` [7][19]. The others are `git status` and `git diff --staged`, a classification of the change and whether it is breaking, a draft in the form `type(scope): imperative summary`, and the final presentation [7]. The tutorial states the split as "let the model decide, let the script verify, and let the script crunch" [16].
That split decides what you can test. A subject-length limit written as a sentence in Markdown is checked by whichever model happens to load the file; the same limit in Python is checked the same way every run. The tutorial's framing is that prose instructions alone make the result harder to verify when the agent has to count characters, parse a file, or refuse to overwrite an existing artifact [20]. The example repository tests its skills with Python's standard library [14], though the tutorial text stops before the test file itself; the instruction is to test the script independently [17].
The rules that stay in prose are the three Nevers: never stage files yourself, never commit secrets or unrelated files, never add an AI attribution footer unless requested [8]. The exit codes say nothing about them. They hold up because the workflow contains no unconditional commit, so the skill can prepare and validate a message without changing repository history [9]. Exit 2 covers input handling and nothing else: it keeps a missing message file from being reported to the user as a bad subject line [5].
Activation is decided in the front matter. The agent may read only the `description` field while deciding whether to activate the skill [10]. So the tutorial's description spells out the triggers: the user asks to commit, asks for a commit message, wants to fix or improve a commit message, or mentions conventional commits [11]. `name` must match the parent directory and use lowercase letters, numbers and single hyphens [12]. Discovery is literal. The install path sets the scope: `.agents/skills/commit-crafter` ties the skill to one repository, `~/.agents/skills/commit-crafter` makes it available across projects, and the tutorial says to check your agent's discovery rules before installing globally [15].
For any of this to transfer, one thing has to be true on your side: your agent discovers skills from a supported skills directory [13]. The rest of the minimal path is Python 3.9 or newer and a git repository with staged changes if you want to run the commit flow [13], with no API key, no hosted model and no third-party Python package [14].
What to watch
- Whether exit code 2 for missing input becomes a convention across skill scripts or stays one repository's choice.
- Whether agent runtimes begin reading more than the description field when deciding to activate a skill.
- Whether the tutorial repository publishes the test file for check_message.py alongside the skill itself.