Skeptic intercepts Claude Code's plan mode and gives you up to three objections from a senior engineer who has seen this idea fail before. If the plan is fine it stays quiet. That's the whole product.
claude plugin marketplace add doramirdor/skeptic
claude plugin install skeptic@skepticFree. Open source. Runs locally. No account.
Coding agents will do what you ask. They will install the dependency. They will write the form. They will build the abstraction. They will not stop to ask whether the thing you asked for is the thing you actually want.
A senior engineer would. They would say: you do not need a custom
CheckoutForm, Stripe ships one. You do not need a fetch wrapper, you already
import axios. You do not need GraphQL, you have three slow endpoints. They
would say it in a sentence and you would change your mind.
Skeptic is that sentence.
- You enter plan mode in Claude Code (
Shift+Tabcycles, or--permission-mode plan). - Claude makes a plan and calls
ExitPlanModeto present it. - Skeptic intercepts the call via a
PreToolUsehook, spawns a fresh Claude session with the critic prompt, and feeds it the plan plus a small context bundle (CLAUDE.md, your package manifest, recent diffs). - The critic returns 0–3 objections. If
proceed, the hook exits silently and the plan runs. Ifobject, the hook blocks the call and hands the objections back to Claude, which revises.
Everything runs on your machine. The only network call is the one your Claude Code session already makes.
claude plugin marketplace add doramirdor/skeptic
claude plugin install skeptic@skepticVerified end-to-end: claude plugin validate passes and the PreToolUse
hook loads with no model-context cost.
If the plugin manager isn't available or you want to pin a fork:
git clone https://github.com/doramirdor/skeptic ~/.skeptic-srcThen add to ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "python3 ~/.skeptic-src/hooks/on_plan.py"
}
]
}
]
}
}No SKEPTIC_BACKEND needed — the hook auto-detects (see below).
Skeptic picks a backend for you — no configuration needed.
| Backend | Auth | Latency | Picked when |
|---|---|---|---|
api |
ANTHROPIC_API_KEY |
~3–5s | that env var is set |
cli |
Your Claude Code subscription | ~30–90s | it isn't — works for every Claude Code user |
A subscription-only user with no API key gets the cli backend
automatically, so Skeptic does something useful the moment it's installed.
Set SKEPTIC_BACKEND=api or SKEPTIC_BACKEND=cli to override.
Every mode runs the same critic against the same plan. They only differ in
voice. The 1–3 objection cap, the 90-token limit, the JSON contract, and the
"return [] if the plan is fine" rule apply to every mode.
/skeptic <name> |
What it sounds like |
|---|---|
default |
Senior engineer, fifteen years in. Tired but not mean. |
harsh |
Same engineer, has had a bad week. Will not soften. |
karen |
Performative complaint voice. Asks to speak to whoever scoped this. |
stoic |
Marcus Aurelius. Short, declarative, no adjectives. |
shakespeare |
Iambic pentameter. The objection still has to be correct. |
axios |
Grounds every objection in your own codebase. |
/skeptic harsh # switch mode (persists in ~/.skeptic/config.json)
/skeptic off # pause for the session
/skeptic on # resume
/skeptic stats # how often did Skeptic object this week
/skeptic last # replay the last objection in full| Field | Source |
|---|---|
user_request |
most recent user message from the transcript |
plan |
the plan arg passed to ExitPlanMode |
project_context.claude_md |
<cwd>/CLAUDE.md, capped at 4KB |
project_context.package_manifest |
first match of package.json, pyproject.toml, Cargo.toml, go.mod, Gemfile |
project_context.recent_diff |
git diff HEAD~5..HEAD --stat, capped at 2KB |
mode |
SKEPTIC_MODE env var or ~/.skeptic/config.json |
The 3-second git diff timeout means non-git directories add no latency.
Skeptic is fail-open: any error path (missing API key, network failure,
timeout, malformed model output) lets the plan proceed and logs to
~/.skeptic/debug.log. A broken Skeptic is invisible, not annoying.
The critic prompt is 80% of the product, so it has tests.
pip install anthropic
python evals/run.py # api backend, ANTHROPIC_API_KEY
python evals/run.py --backend cli # uses your Claude Code subscription
python evals/run.py --seeds stripe-payments # one seed at a timeThe 8-seed suite covers dependency bloat, reinventing-paid-services, scope
creep, expand-contract migrations, and two proceed cases. Current
suite-level proceed-rate: 25%, dead center of the 20–35% target band from
critic.md. See evals/README.md for the
scoring rubric and the four prompt-degradation regressions the suite is
designed to catch.
The highest-leverage contribution is a new mode.
- Add
prompts/modes/<your-mode>.md— a single overlay file describing the voice. Keep it short; the base prompt does the heavy lifting. - Add the mode name to the list in critic.md.
- Add at least one seed in
evals/seeds/that exercises the new mode. - Open a PR.
See CONTRIBUTING.md for the full guide, including how to add seeds and how to debug the hook locally.
MIT. See LICENSE.