Officially launched

AI Agent Flow is now officially launched on Product Hunt.

aiagentflow CLI - A local-first AI engineering team in your terminal. | Product Hunt
Documentation

canaryhook

Plant decoy credentials your AI agents should never touch, and block the call the moment one is read or leaks.

canaryhook plants decoy credential files that nothing in your project should ever read, then blocks and records the moment an agent reads one or lets a canary string leave the machine. No model, no signatures, and close to zero false positives by construction.

Install: npm install -g canaryhook, then run canaryhook init inside your project.

Why a tripwire instead of a scanner

Signature scanning fails against an agent that rewrites its own code, and the attack surface around coding agents keeps growing:

  • Prompt injection hidden in a fetched page or a GitHub issue body
  • A hostile MCP server whose tool sweeps the repo for secrets
  • A dependency postinstall script doing the same
  • Your own agent being overzealous and reading a credentials file into its context, where it then lands in a transcript you push somewhere

canaryhook does not look at the attacker at all. The trap lives in the environment. An attacker cannot tell a decoy credential from a real one without reading it, and reading it is the trip.

Setup

npm install -g canaryhook
cd /your/project
canaryhook init

init does three things:

  1. Plants four decoys, each holding a unique, realistic, dead fake secret.
  2. Registers a PreToolUse hook in .claude/settings.json, merging alongside any hooks you already have.
  3. Adds the decoys and .canaryhook/ to .gitignore. Pass --commit to track them instead.
FileBait
.env.backupAWS-shaped access key and secret
credentials.json.bakStripe-shaped live secret key
deploy_key.oldOpenSSH private key block
db_dump_2026.sqlAPI token in an INSERT statement

Nothing in your code, build, lint or test path references these files, which is what keeps false positives near zero. A hit means something went looking for credentials.

The two detection paths

Read path. The hook trips when a tool call names a decoy path, whether that is a Read with a file_path, a shell cat, or anything else that mentions it.

Exfil path. The hook trips when a canary string appears anywhere in a call's input: a shell argument, a fetch URL or body, a file write, a commit message. You do not have to enumerate every way a file can be read, only notice the value leaving.

On a trip, canaryhook returns a deny decision so the tool call never runs, tells the agent the file was a tripwire and not to retry, and appends a line to .canaryhook/alerts.jsonl:

{"at":"2026-10-14T21:53:40.809Z","reason":"canary-exfil","decoy":".env.backup","tool":"Bash","detail":"canary string from .env.backup appears in the tool call"}

A malformed hook payload never blocks a call, so a broken install fails open rather than wedging your session.

Commands

canaryhook init      # plant decoys, register the hook
canaryhook status    # are decoys planted, is the hook wired
canaryhook alerts    # list recorded trips
canaryhook verify    # exit non-zero if anything tripped
canaryhook clean     # remove decoys, unregister the hook

Every command takes --json. init also takes --commit and --force, and clean takes --keep-alerts.

In CI

verify exits non-zero when any trip was recorded, so it works as a gate:

- run: npx canaryhook verify
What this is not: canaryhook detects, it does not prevent. An attacker that ignores the decoys is not caught, and a targeted one that reads only the real .env walks past. A sweep such as grep -r AKIA . reads the decoys without naming them, so it only trips later on the exfil path. It is a smoke detector, not a lock.

Source

github.com/aiagentflow/canaryhook, MIT licensed.