We are going to set up the safety net before building anything. This is deliberate. A net installed after the fall is a decoration.
Get the pack
git clone https://github.com/RasaHQ/rasa-community-resources.git
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:
| What | Job |
|---|---|
CLAUDE.md | The 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.py | The lint. One file, standard library only, no installation needed |
hooks/ | The git hook and its installer |
.claudestarts with a dot, so your file browser hides it.ls -aproves 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 nine 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 9 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:
- It is not a cage.
git commit --no-verifybypasses 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. - It refuses to run blind. If
scripts/lint_mantle.pygoes 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 inhooks/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-commithook run at, and what does ours do there? - Where would you look to understand what the
secret-hygienecheck actually scans for? (Answer: its function inlint_mantle.py— the docstrings are the documentation.)
Net installed. Time to build something worth catching.
