Skip to content
RasaGet a free licence
Menu

tutorial

Chapter 1 of 4

Install the Rasa Mantle lint and git hook before building

by Rod Rivera Published

Install the starter pack, meet the lint, and wire up the git hook — with a plain-English explanation of what those words even mean.

Before building Juniper, the fictional plant-shop assistant, you will install a configuration checker and a Git commit hook. The checker looks for known misplaced settings; the hook runs it when you commit a change.

You will first run the checker on an empty project and inspect its findings. Later, the same checks will help you review the assistant’s configuration while you build it.

Get the pack

git clone https://github.com/RasaHQ/rasa-community-resources.git
git -C rasa-community-resources checkout 4aa0c4419dc193fef7a969c12d59edcf720f2606
mkdir juniper && cd juniper
git init

cp -R ../rasa-community-resources/starter-pack/CLAUDE.md .
cp -R ../rasa-community-resources/starter-pack/.claude .
cp -R ../rasa-community-resources/starter-pack/scripts .
cp -R ../rasa-community-resources/starter-pack/hooks .

Four things just landed in your empty project:

WhatJob
CLAUDE.mdThe rulebook Claude Code reads automatically — version doctrine plus the five silent traps, so the assistant can’t “helpfully” reproduce them
.claude/Six skills (build playbooks) and two roles (a builder, a reviewer). Browse them on GitHub — they are readable Markdown, useful to humans too
scripts/lint_mantle.pyThe lint. One file, standard library only, no installation needed
hooks/The git hook and its installer

.claude starts with a dot, so your file browser hides it. ls -a proves it’s there.

Meet the lint

A linter is a program that reads your files and points at known mistakes — named after picking lint off clothing. This one has ten checks, and it has a property worth pausing on: every check corresponds to a failure a real, shipped Mantle project actually experienced. Not hypothetical style rules. Scar tissue, mechanized.

Run it right now, in your nearly-empty project:

python3 scripts/lint_mantle.py
[engine-version-pin] pyproject.toml: missing pyproject.toml
[secret-hygiene] .gitignore: '.env' is not gitignored — one 'git add -A'
    away from publishing credentials
[env-example] .env.example: missing .env.example — a new user has no way
    to discover which credentials this project needs

FAILED — 3 finding(s) across 10 check(s)

This failure is the success. Three findings on an empty project means the checker is alive, and — read them again — each finding tells you what’s wrong, why it matters, and what to do. That is the contract every message in this lint keeps. You never get a bare “error 47”.

You can also run one check at a time, or list them all:

python3 scripts/lint_mantle.py --list
python3 scripts/lint_mantle.py --check secret-hygiene

If you’re curious how any check works, the answer is one click away: each check in lint_mantle.py is a short function whose docstring tells the story of the failure it encodes. The file is meant to be read.

Wire the hook

A git hook is a small program git runs automatically at a key moment. The one we install runs at pre-commit — the instant before git saves a snapshot of your work:

./hooks/install-hooks.sh
Installed: .git/hooks/pre-commit
Every commit now runs: python3 scripts/lint_mantle.py

From now on, committing a known trap gets you this instead of a saved bug:

COMMIT BLOCKED by lint_mantle.py (exit 1).
Each finding above names its fix. The checks encode real, silent
failures — fixing them now is cheaper than debugging them at train time.

Two things to know about the guard, because trust requires understanding:

  1. It is not a cage. git commit --no-verify bypasses it. The etiquette: if you bypass, say why in the commit message. The lint only complains about mistakes that are silent at runtime, so a bypass usually means shipping a bug you won’t meet again for weeks — make it a decision, not an accident.
  2. It refuses to run blind. If scripts/lint_mantle.py goes missing, the hook blocks the commit rather than waving it through — a safety net with a hole in it is worse than none, because you stop looking down. (You can read this logic in hooks/pre-commit — it’s 25 lines.)

The installer is also polite: if you already had a pre-commit hook from something else, it refuses to overwrite it and tells you to merge them yourself.

Check your understanding

Before Chapter 2, you should be able to answer:

  • Why did the lint fail on an empty project, and why was that good news?
  • What moment does a pre-commit hook run at, and what does ours do there?
  • Where would you look to understand what the secret-hygiene check actually scans for? (Answer: its function in lint_mantle.py — the docstrings are the documentation.)

Net installed. Time to build something worth catching.