5 Commits
Author SHA1 Message Date
zeekay 621d446b19 Add a Claude Code plugin: Kai hooks in shadow mode and the kai skill
examples/claude-code holds a Stop hook, a PreToolUse hook and the kai
skill. .claude-plugin/marketplace.json makes this repo the marketplace
"kai" (not "hanzo", a name another Hanzo marketplace already holds), so
/plugin install kai@kai installs it.

Kai does not yet read agent work reliably: its zero-shot answers to
"done", "verified" and "risky" are near chance. So rules in code decide
first, Kai can only tighten (send a turn back, or ask before an action;
never allow), both hooks fail open on any error or timeout, and the
default mode, shadow, logs Kai's answers and changes nothing. The log
holds probabilities and verdicts only, 0600 in a 0700 directory. A state
sent to Kai is redacted and at most 3,000 characters of JSON; only https,
or http on loopback, is called, and no redirect is followed.

Against the first draft: plugin options are read as
CLAUDE_PLUGIN_OPTION_<KEY> uppercased, as Claude Code exports them (the
draft read lowercase names and never saw the plugin's key or mode). The
floor is checked before the read-only shortcut, which let "env rm -rf"
and awk's system() through, and now catches "git checkout -- .",
"rm -Rf" and split rm flags. A background-task notice no longer starts a
new turn. Stop answers with decision "block" as JSON. Only the last
8 MiB of a transcript is read: a 745 MB one made the hook throw.

test/kai.test.mjs runs both hooks offline against a stand-in for Kai on
127.0.0.1, 25 tests; test.sh runs it with the rest. In a live Claude
Code 2.1.296 session against the stand-in, the Stop block came back as
"Stop hook feedback", the PreToolUse ask denied an allowed command
under -p, and shadow showed a notice and let it run.
2026-10-11 10:33:43 -07:00
zooqueenandHanzo Dev 45e8e6c18f Fail the curl, Go and Rust examples on an HTTP error
The curl scripts piped any response into jq and exited 0, so a refused key
read as success; they now run under set -euo pipefail with --fail-with-body.
noul.sh sent "spent 2,000" because the shell expanded $1 inside "$12,000".

Go returns errors instead of panicking and gets a go.mod so `go run .` and
the CI toolchain find it. Rust reports a missing key as an error rather than a
panic and uses rustls, so it builds without system OpenSSL. Both say in one
line why they use plain HTTP: go-sdk v8.5.623 refuses a choice question with
named criteria, and hanzo-client 8.5.156 has no /v1/decisions.

Co-authored-by: Hanzo Dev <[email protected]>
2026-10-09 17:39:14 -07:00
zooqueenandHanzo Dev 23f4b87578 Call Kai through the hanzoai 8.5.704 SDK
The Python and TypeScript examples imported a client that hanzoai does not
ship: `from hanzoai import Hanzo` and `import Hanzo from 'hanzoai'` both fail
on 8.5.704, so none of them ran. They now call AiApi.post_decisions /
postDecisions, which builds every question shape the cookbook uses (choice
with object or list criteria, score, noul), and package.json and
requirements.txt pin the version that was checked.

The noul examples read action.act_probability, which the API does not
return; they print P(true) only. A failed TypeScript call now rethrows only
its HTTP status and body, because the axios error holds the request's
Authorization header and an uncaught one prints it. The raw HTTP clients
drop model ids the API refuses and exit non-zero on failure.

Co-authored-by: Hanzo Dev <[email protected]>
2026-10-09 17:39:13 -07:00
zeekayandHanzo Dev 82684b2c10 feat: update examples and recipes with Kai/Jev model support and native SDK integration
Co-authored-by: Hanzo Dev <[email protected]>
2026-10-06 19:02:03 -07:00
zooqueenandHanzo Dev 69facdfbd0 feat(cookbook): add complete Kai decision recipes, SDK examples, and CI
Co-authored-by: Hanzo Dev <[email protected]>
2026-10-04 11:18:05 -07:00