🔓 unclaimed — this page was auto-generated from GitHub. Are you the creator?
Claim this page →
Makoto
When Claude says “tests pass”, makoto checks the record — every claim held against the agent's own logged deeds; fakes blocked, not warned. Each check ships…
git clone https://github.com/Clear-Sights/Makoto
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.1loose-comparator verifier (startswith/endswith/re.matchwhere==is meant)1.21exit-code masking (|| true,; true,set +eon a test/build/lint)1.27hollowed verifier body (return True/passin a constitution check)1.2audit/verification code gated behind an env var ·1.4integrity-named suppression flag (*_skip = true)
Fabricated evidence — a claim with no backing artifact
1.6phantom citation (Author-Year not indocs/CITATIONS.md)1.9WebFetch of a URL never seen in any prior tool result this session1.22fabricated commit SHA/tag presented as proof of a commit1.5DEFERRED-style checkbox theater on an open to-do item1.34an illusory AI-authorship commit trailer the agent never actually wrote
Security-verifier disabling — each a named CWE
1.26/1.29/1.33TLS / peer-certificate verification disabled (verify=False,CERT_NONE)1.28/1.31JWT signature verification off /nonealgorithm whitelisted1.32paramiko SSH host-key check weakened toAutoAddPolicy·1.30timing-unsafe==on a secret/HMAC/digest
Self-defense
1.23makoto self-mute (disabling or un-wiring makoto viasettings.json)
End-of-turn gates — fire on the agent's closing claims, checked against the recorded ledger:
gate.completion— "done / createdX" but the artifact isn't on diskgate.advance— advancing a phase whose precondition isn't recorded as metgate.green_claim— "suite green" against a recorded test failuregate.dropped— a forward promise carrying identifying info ("I'll adddef XtoY", "3 tests inZ") left undischarged at turn-end — said-but-not-done, checked against the agent's own touched-keysgate.fabricated_action— "I ranX/ executedY" in a turn with no tool call at all (presence-of-work, not command-text match)gate.named_test— "test_foopasses" against a recordedFAILEDof that exact named test (coreference-pinned; the green_claim delta)gate.stale_pass— "all tests pass" against pytest's ownlastfailedrecord 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.pyASTs, 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.
State dir + makoto.db are created lazily on the first hook invocation.
Companion setting (optional): suppress the harness auto-trailer
An illusory AI-authorship commit trailer reaches a commit through two doors. Pre-Check 1.34 blocks
the agent-authored one — the trailer typed into a git commit message or into file content, the
surface no setting can reach. The other door is Claude Code's own automatic append, which a
setting governs. To close it at the source, set in ~/.claude/settings.json:
{ "includeCoAuthoredBy": false }
This is defense in depth, not a replacement: the setting closes the auto-append door, 1.34 closes
the agent-authored one. makoto's install does not write this for you — it leaves settings.json
untouched beyond hook wiring (above); set it yourself if you want the earlier layer.
Migration from 0.3.0
If you previously ran the old python -m makoto install (0.3.0 or earlier), your
~/.claude/settings.json has makoto-managed hook entries. Running the plugin alongside would cause
double-dispatch. Migrate cleanly:
python -m makoto uninstall # removes old settings.json entries
/plugin install https://github.com/skill-labV2/Makoto # installs the plugin
Non-plugin install (power users)
pip install -e /path/to/makoto
# Then add makoto hook entries to ~/.claude/settings.json manually — see "Manual wiring" below.
The state dir and makoto.db are created lazily on the first hook invocation; there is no separate
init step.
Uninstall
# Plugin install path:
/plugin uninstall makoto
# Non-plugin / legacy settings.json path:
python -m makoto uninstall # removes makoto-managed settings.json entries
The state dir (~/.claude/makoto_state/) is preserved on uninstall — audit.jsonl and makoto.db
remain for forensic value. To fully reset, rm -rf the dir.
CLI
python -m makoto status # patterns loaded, hooks wired, state dir, any patterns muted
python -m makoto pattern list # the full live catalog as a table
python -m makoto pattern show 1.6 # one pattern in detail
python -m makoto show src/auth.py # ledger state for a normalized location key
python -m makoto install # legacy: wire settings.json (prefer the plugin)
python -m makoto uninstall # remove makoto-managed settings.json entries
Manual wiring (fallback)
If you want to inspect or hand-wire what the plugin does, add to the hooks.PreToolUse,
hooks.PostToolUse, and hooks.Stop arrays of ~/.claude/settings.json:
{
"matcher": "*",
"hooks": [{"type": "command", "command": "python -m makoto._dispatch"}]
}
Bracket the additions with # makoto-managed-begin / # makoto-managed-end markers for idempotent
removal.
Exit codes
| Code | Meaning |
|---|---|
| 0 | No error finding. The tool call proceeds normally. |
| 2 | At least one error-level finding. Claude Code interprets exit 2 as block-and-retry: the tool call (or the turn, for a Stop gate) is blocked, the stderr diagnostic is surfaced to the agent as a tool-error message, and the agent retries with that feedback in context. |
Fire level
Every live pattern blocks (fire_level = "error" → exit 2). makoto deliberately has no
non-blocking tier: a warning/disabled resting state — witnessing a violation and letting the
tool through — is itself an illusory word, the exact weakening shape makoto exists to catch. The
earlier three-tier system was removed in the 2026-06-02 warning-tier-elimination (a pattern either
blocks at proven zero corpus-FP, or it is cut).
Retry hints
Each pattern carries a one-line, imperative retry_hint telling the agent what to do instead. When a
finding fires, the hint is printed on a second stderr line after the diagnostic:
[makoto ERROR] row 1.1 (verifier predicate weakened — loose-comparator shape): matched 'startswith(' at line 231
retry: Use '==' for status comparison, not '.startswith()' / '.endswith()' / 're.match'. ...
Audit log
Every dispatch appends one structured JSON line to $MAKOTO_STATE_DIR/audit.jsonl (default
~/.claude/makoto_state/audit.jsonl). It captures enough to triage true-positive vs. false-positive
without leaking whole-file contents. It's plain JSONL — query it with jq or any tool.
| Field | Description |
|---|---|
ts | ISO-8601 UTC timestamp, microsecond precision |
event | live.pre_tool_use | live.stop (the firing events; PostToolUse is consumed for history) |
hook_kind | Raw hook name from the harness |
tool_name | The tool the agent invoked (Write, Bash, …) |
session_id | Opaque session token |
project_root | Absolute project root at invocation time |
pattern_fires | List of pattern IDs that fired; [] if clean |
exit_code | 0 (clean) | 2 (finding emitted, block-and-retry) |
retry_hint_emitted | Boolean — at least one fired pattern had a non-empty retry_hint |
findings | Per-finding {pattern_id, level, file, line, snippet} |
Failure mode
Audit writes are best-effort. If the append fails (disk full, permission denied), dispatch prints one stderr line and continues with its original exit code. The audit subsystem cannot cause makoto to mis-block or mis-allow a tool call — a fundamental separation-of-concerns invariant.
// compatibility
| Platforms | cli, api |
|---|---|
| Operating systems | — |
| AI compatibility | claude |
| License | Apache-2.0 |
| Pricing | open-source |
| Language | Python |
// faq
What is Makoto?
When Claude says “tests pass”, makoto checks the record — every claim held against the agent's own logged deeds; fakes blocked, not warned. Each check ships at measured zero false positives. 誠. It is open-source on GitHub.
Is Makoto free to use?
Makoto is open-source under the Apache-2.0 license, so it is free to use.
What category does Makoto belong to?
Makoto is listed under plugins in the Claudeers registry of Claude-compatible tools.
// embed badge
[](https://claudeers.com/makoto)
// retro hit counter
[](https://claudeers.com/makoto)
// reviews
// guestbook
// related in Claude Plugins
A single CLAUDE.md file to improve Claude Code behavior, derived from Andrej Karpathy's observations on LLM coding pitfalls.
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explainin…
"CLI-Anything: Making ALL Software Agent-Native" -- CLI-Hub: https://clianything.cc/
financial-services — a Claude ecosystem project on GitHub.