Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

⌗ Reflex

Reflex makes AI coding agents reach for the right tool — by default, not by luck.

mission license platform tools agent

What & Why · Philosophy · Measurement · Quickstart · The Four Layers · Layout


What & Why

AI coding agents don't have a capability problem — they have a habit problem.

The agent knows jq exists. It still pipes JSON through grep. It knows crudini can edit an INI file surgically. It still reaches for sed -i and corrupts the next key. It knows dwdiff exists, and still drowns you in line-noise from raw diff. The model has read the man pages — but at decision time, the muscle memory is grep/sed/awk and a fistful of Edit calls.

(These are the failure modes the tools are designed to prevent. Whether they net-reduce tokens or errors in practice is a hypothesis we are still measuring — see Measurement.)

Reflex fixes the habit, not just the toolbox. It does two things:

  1. Installs a tight, curated core of agent-friendly CLI tools (12 Homebrew/pipx packages, 13 commands — run tools/toolcount.sh) — headless, scriptable, deterministic, machine-parseable. The exact traits that made them awkward for a human at a live terminal are the traits an agent wants. No kitchen sink; these are the ones that earn their place.
  2. Wires the agent (Claude Code) to actually lean on them — through a deterministic hook, an always-in-context preference table, a recalled memory, and an on-demand skill.

That's the whole product: a curated core plus the wiring that makes the agent use it. These were chosen from a much larger survey of candidate tools — only the ones that earned their place on an agent's PATH are installed here.

Philosophy

Installing a tool changes nothing if the defaults win.

Behavior change doesn't come from what's on the machine. It comes from what's in the agent's context at the moment it decides what to type. A tool the agent never recalls is a tool that doesn't exist.

So Reflex treats the deterministic hook as the backbone — it fires on every command, whether or not the model "remembered" — and treats the table, the memory, and the skill as reinforcement that compounds. Layered, the reflex changes. Tools without wiring is a wish; wiring without tools is a nag. You need both.

These are aids, not laws. When the boring tool is genuinely clearer for a one-off, the agent still uses it. The goal is better defaults, not new dogma.

Measurement

Reflex's mechanism is verified: the hook deterministically blocks the named wrong idioms and re-routes the agent (see tests/test_hook.py). Its efficiency — fewer tokens, fewer tool calls, higher first-try correctness — is a hypothesis, not a measured result. We ship local telemetry (~/.reflex/events.jsonl, opt-out) so a with/without benchmark can produce and audit the number before it is claimed. Until that benchmark is published, treat efficiency claims as unproven.

Rule for future copy: treat every comparative claim (faster / cheaper / more correct / beats / inferior) as an unproven hypothesis until a published benchmark cites a number.

Quickstart

git clone https://github.com/campbellcharlie/reflex.git ~/src/reflex
cd ~/src/reflex
./install.sh            # installs tools + wires Claude Code config
# then in Claude Code: open /hooks once (or restart) to load the hook

Piecemeal:

make tools     # just install the CLI tools (brew + pipx)
make claude    # just wire the Claude Code layers
make verify    # show which toolkit commands are on PATH

Target a non-default config dir: CLAUDE_HOME=/path/to/.claude make claude.

What gets installed

jc · jq · gron · dwdiff · sem (GNU parallel) · augtool (augeas) · hxselect (html-xml-utils) · unbuffer/expect · gstdbuf (coreutils) · crudini (pipx) · datamash · tmux, plus system lsof/ed. All verified on macOS 27. See tools/install-tools.sh. The tool list and its count (12 packages / 13 commands) are generated from tools/manifest.tsv — run tools/toolcount.sh to reproduce every number here.

Telemetry (local-only, opt-out): the hook appends one JSON line per Bash decision to ~/.reflex/events.jsonl — only the decision class (block/advise/raw/allow), the suggested tool, and whether it was on PATH. No command text, arguments, cwd, or env is ever recorded, so the file is safe to share. It is never transmitted anywhere. Opt out with REFLEX_TELEMETRY=0; relocate the directory with REFLEX_HOME=/path.

jq is the keystone — jc and gron both pipe into it — so the installer ensures it rather than assuming it's present.

tmux is the one mainstream pick — it's installed because send-keys + capture-pane -p is the best persistent-session driver an agent has. It's not a macOS default; macOS ships /usr/bin/screen as a weaker zero-install fallback.

Deliberately not auto-installed (collisions / unpackaged):

  • real pup — brew pup is the Datadog CLI; use hxselect or go install github.com/ericchiang/pup
  • flock/lockf — use sem
  • spiff — archival source
  • sam/ssam — needs plan9port

The Four Layers

Installing tools changes nothing if defaults win — so the change comes from four reinforcing layers, with the deterministic hook as the backbone.

Layer File What it does
1 · PreToolUse hook (deterministic) claude/hooks/toolkit-nudge.py On every Bash call, classifies the command. Tier A blocks the high-confidence wrong idioms (grep/sed/awk on a .json file, sed -i on a config file) via permissionDecision:deny, feeding the right tool back so the agent re-routes. Tier B advises the fuzzier ones (ps|awk, curl|grep HTML). Append # raw to override a block.
2 · CLAUDE.md table (always in context) claude/CLAUDE.snippet.md A "Preferred Tooling" reach-for-A → use-B table appended to ~/.claude/CLAUDE.md.
3 · Memory entry (recalled) claude/memory/agent-cli-toolkit.md Persistent note of the toolkit + preference, dropped into your auto-memory dir.
4 · toolkit skill (depth on demand) claude/skills/toolkit/SKILL.md The full pairing map, auto-loaded when relevant work starts.

claude/install-claude.sh wires layers 1, 2, and 4 idempotently (re-running re-applies snippet updates, not just appends-once). merge-settings.py merges the hook into settings.json without clobbering existing hooks and backs it up to settings.json.bak. Layer 3 (the memory note) is not auto-installed — copy claude/memory/agent-cli-toolkit.md into your auto-memory directory yourself if you use auto-memory.

Hook tuning

The hook is two-tier. A small BLOCK list — grep/sed/awk on a .json file, sed -i on a config file — denies the command (permissionDecision: "deny") with a message naming the right tool, so the agent re-routes instead of running the wrong thing. A larger ADVISE list (ps|awk, HTML scraping) only injects a tip; the command still runs. Three guards keep blocking safe: patterns are anchored to a command position (start, or after |/;/&&) to avoid false positives; a block never fires toward a tool that isn't installed; and appending # raw to a command bypasses the block for genuine exceptions (malformed JSON, raw context). To loosen, move a pattern from BLOCK to ADVISE in toolkit-nudge.py; to tighten, do the reverse.

(Note: blocking is done with the stdout permissionDecision: "deny" form, not a bare exit 2 — the registered hook command wraps the script in || true, and this Claude Code surface acts on the JSON decision, not the exit code.)

Uninstall
  • Remove the PreToolUse "Bash" entry from ~/.claude/settings.json (restore ~/.claude/settings.json.bak).
  • Delete ~/.claude/hooks/toolkit-nudge.py and ~/.claude/skills/toolkit/.
  • Remove the "Preferred Tooling" section from ~/.claude/CLAUDE.md.

Layout

install.sh              # tools + claude
tools/install-tools.sh  # brew + pipx, idempotent
claude/
  install-claude.sh     # wire the 4 layers
  merge-settings.py     # idempotent settings.json hook merge
  merge-claudemd.py     # idempotent CLAUDE.md section insert/replace
  hooks/toolkit-nudge.py
  skills/toolkit/SKILL.md
  CLAUDE.snippet.md
  memory/agent-cli-toolkit.md
tests/test_hook.py      # hook allow/deny/advise suite (make test)

License

MIT © 2026 Charlie Campbell

About

Make AI coding agents reach for the right CLI tool by default — a curated 14-tool toolkit plus a deterministic Claude Code hook that blocks bad shell idioms.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages