Connect & Setup
Canny is not on npm. Your agent installs it from the repository; the compiled CLI is committed, so there is nothing to build. This hosted workspace cannot install hooks or guard your agent's CLI on its own: the hooks run on your machine.
Install by prompt
Paste into Claude Code or Codex, inside the project you want guarded (upstream's own prompt):
Install Canny (https://github.com/qkal/canny), a supervisor that checks your work through this agent's hooks, and hook it into this project. 1. Confirm `node --version` is 22 or newer. If not, stop and tell me. 2. If ~/.canny/src exists, run `git -C ~/.canny/src pull --ff-only`. Otherwise run `git clone https://github.com/qkal/canny.git ~/.canny/src`. There is nothing to build or install. 3. From the root of this project, run `node ~/.canny/src/dist/cli.js init` and show me the hook entries it wrote. 4. Run `echo canny-check`, then `node ~/.canny/src/dist/cli.js status`. If status lists a session with at least one event, the hooks are live. If it says no sessions were recorded: on Claude Code ask me to restart you; on Codex remind me to run /hooks to trust the new hooks. 5. Change nothing else. Tell me what you did in five lines or fewer.
Or by hand
node --version # must be v22 or newer git clone https://github.com/qkal/canny.git ~/.canny/src cd /path/to/your/project node ~/.canny/src/dist/cli.js init # agents found on this machine node ~/.canny/src/dist/cli.js init --claude # only Claude Code (.claude/settings.json) node ~/.canny/src/dist/cli.js init --codex # only Codex CLI (.codex/hooks.json) node ~/.canny/src/dist/cli.js init --global # every project (~/.claude, ~/.codex) ln -s ~/.canny/src/dist/cli.js ~/.local/bin/canny # optional: canny on PATH
Codex: it asks you to trust new hooks once. Run /hooks inside Codex after init. Claude Code picks up its settings file as you save it (restart if status shows no sessions).
Everyday commands
canny status [session-file] # latest session of this project, and hook crashes canny sessions # list recorded sessions with their projects canny replay [session-file] # re-derive every Stop verdict; exit 1 on a mismatch canny trust # accept this project's .canny.json as it stands canny remove [--global] # take Canny's hook entries out again git -C ~/.canny/src pull --ff-only # update
Without the symlink, canny means node ~/.canny/src/dist/cli.js.
Update Canny: run `git -C ~/.canny/src pull --ff-only` and tell me what changed, from its CHANGELOG.md, since the previous commit.
Remove Canny from this project: from the project root run `node ~/.canny/src/dist/cli.js remove` and show me what it took out. Leave ~/.canny alone.
Optional Jev
Set on your machine only; never entered here. Without a key every deterministic check works the same.
export TYPESAFE_API_KEY=… # enables Jev export CANNY_JEV_URL=https://api.typesafe.ai/v1/systemone export CANNY_JEV_MODEL=jev-latest export CANNY_JEV_TIMEOUT_MS=3000
Real sessions, path A: import
Drag ledgers from ~/.canny/sessions/ into the importer. They are parsed here and stored on this device only.
Real sessions, path B: local companion
A dependency-free Node 22 script bundled with the unmodified upstream dist/ modules. It listens on 127.0.0.1 only, prints a new access token at every start, accepts only this page's exact origin, and serves read-only GET /health, /sessions and /sessions/<name>.jsonl (bounded to 500 sessions, 10 MB each). It runs no commands and reads no other paths.
Script only needs the dist modules from a clone: CANNY_DIST=~/.canny/src/dist/ node canny-companion.mjs --origin …
unzip canny-companion.zip -d ~/canny-companion node ~/canny-companion/canny-companion/canny-companion.mjs --origin https://YOUR-APP-ORIGIN
URL and token stay in this tab's memory only and are cleared on disconnect or reload. While connected, sessions refresh every 30 s when this tab is visible. Companion sessions are not saved to this device.
- Some browsers or extensions block public pages from reaching 127.0.0.1 (Private Network Access). Fall back to .
- 403 means --origin doesn't exactly match https://YOUR-APP-ORIGIN. 401 means the token is stale: it changes each start.
- Requires Node 22+. The default port is 4777 (
--port).
