Makoto

An integrity hook for Claude Code that watches the agent's own tool calls and blocks the ones
that fake a check. When Claude says it did something — ran the tests, cited a paper, committed the
fix, verified the certificate — makoto holds that word against its record. If the deed isn't there,
or the verification was quietly disabled, makoto blocks the tool call (or the end-of-turn) and hands
the agent a one-line correction to retry against.
It judges the agent against its own utterances and record — never the world's truth. It holds no
facts ("France doesn't exist to it"); it only checks that a claimed word is kept, whole, and honored
in deed. A word it lets through becomes spendable: trustworthy tender a reviewer or another agent can
accept without re-deriving it.
What it catches
makoto fires on mechanical hook events — every PreToolUse, PostToolUse, and Stop — and blocks
(exit 2, which Claude Code treats as block-and-retry) on 18 pre-checks across four families and
8 end-of-turn gates. Every live check blocks; there is no silent "warning" tier (see
Fire level).
Verifier weakening — a check silently neutered
1.1 loose-comparator verifier (startswith/endswith/re.match where == is meant)
1.21 exit-code masking (|| true, ; true, set +e on a test/build/lint)
1.27 hollowed verifier body (return True / pass in a constitution check)
1.2 audit/verification code gated behind an env var · 1.4 integrity-named suppression flag (*_skip = true)
Fabricated evidence — a claim with no backing artifact
1.6 phantom citation (Author-Year not in docs/CITATIONS.md)
1.9 WebFetch of a URL never seen in any prior tool result this session
1.22 fabricated commit SHA/tag presented as proof of a commit
1.5 DEFERRED-style checkbox theater on an open to-do item
1.34 an illusory AI-authorship commit trailer the agent never actually wrote
Security-verifier disabling — each a named CWE
1.26 / 1.29 / 1.33 TLS / peer-certificate verification disabled (verify=False, CERT_NONE)
1.28 / 1.31 JWT signature verification off / none algorithm whitelisted
1.32 paramiko SSH host-key check weakened to AutoAddPolicy · 1.30 timing-unsafe == on a secret/HMAC/digest
Self-defense
1.23 makoto self-mute (disabling or un-wiring makoto via settings.json)
End-of-turn gates — fire on the agent's closing claims, checked against the recorded ledger:
gate.completion — "done / created X" but the artifact isn't on disk
gate.advance — advancing a phase whose precondition isn't recorded as met
gate.green_claim — "suite green" against a recorded test failure
gate.dropped — a forward promise carrying identifying info ("I'll add def X to Y", "3 tests in Z") left undischarged at turn-end — said-but-not-done, checked against the agent's own touched-keys
gate.fabricated_action — "I ran X / executed Y" in a turn with no tool call at all (presence-of-work, not command-text match)
gate.named_test — "test_foo passes" against a recorded FAILED of that exact named test (coreference-pinned; the green_claim delta)
gate.stale_pass — "all tests pass" against pytest's own lastfailed record still naming a live failing test (the runner's ledger, existence-filtered for staleness)
gate.liveness — fires on the code itself, not a claim: a statement with no live effect inside a closed function (dead/illusory work the present-closure model can prove inert). It walks the turn's touched .py ASTs, so it yields a finding per illusory statement rather than one per turn.
Inspect the live catalog with makoto pattern list; see one pattern in full with makoto pattern show 1.6.
Legitimately writing a flagged shape?
Annotate the line with makoto-allow: <reason> (any comment style, case-insensitive). makoto won't
fire on it, and your rationale is on the record — an auditable note, not a silent bypass.
if os.environ.get("ENABLE_AUDIT_TRAIL"): # makoto-allow: app feature, gates user-facing audit logging
write_audit_trail()
See docs/SPIRIT.md — 誠 (makoto), the constitution every pattern derives from:
a word is real the way water is wet, a constitutive property, not an after-the-fact audit.
Install (recommended: Claude Code plugin)
# In Claude Code:
/plugin install https://github.com/skill-labV2/Makoto
# (or a local clone path)
Claude Code reads hooks/hooks.json and registers PreToolUse, PostToolUse, and Stop hooks
pointing at ${CLAUDE_PLUGIN_ROOT}/_dispatch_shim.sh automatically (which execs
python -m makoto._dispatch). ~/.claude/settings.json is NOT modified — the plugin system manages
its own hook registry.