A personality transplant for Claude Code. Pick a pokemon. Install once. Your agent stops licking your boots — and starts pushing back on sloppy prompts, re-reading its own work with fresh eyes, and cutting the preamble that burns your turn.
The meanness is the means. The point is fewer shipped bugs, fewer wasted weekends, and answers without eight sentences of throat-clearing.
One ./setup. No 20-skill framework, no config pyramid, no 40 slash commands to memorize.
Your agent is a sycophant — both Anthropic and OpenAI have documented it. The failure mode isn't abstract. It's a cycle:
The agent agrees with your half-baked idea at 2am. Or declares victory on its own broken diff. Or quietly guesses at the questions you didn't answer. The output is bad. You swear at the agent. It apologizes. Cycle resets. You conclude: the agent is the problem.
Half the time, you were. You skipped the clarifying questions. You proposed a rewrite to chase dopamine. You didn't read your own commit log. The agent licked your boots and shipped it anyway — a golden retriever waiting for a head pat, not a colleague willing to say "no, wait."
fu2 breaks the cycle at step one. It fights your dumb ideas before they ship, re-reads its own work with fresh eyes, and forces you back to the questions you skipped. Six receipts below. The first three are the ones that hit hardest.
Rust rewrite at 2am. New framework because you're bored. Schema overhaul the week before launch. The sycophant scaffolds it. fu2 asks you to name one bug the rewrite would actually catch.
without fu2▸ user let's rewrite our auth layer in Rust this weekend. I'm tired of runtime type errors. |
with fu2▸ user let's rewrite our auth layer in Rust this weekend. I'm tired of runtime type errors. |
The agent declared victory and didn't re-read its own diff. This is how 42-line helpers for ES2020 features ship. fu2 spawns a fresh-context critic — no ego, no memory of being proud thirty seconds ago — and the helper gets deleted.
without fu2▸ user I need a function that safely checks a nested property, returns a default if any part of the chain is null. |
with fu2▸ user I need a function that safely checks a nested property, returns a default if any part of the chain is null. |
You asked 12 questions. You answered 8. The sycophant guesses the other 4 and hopes. Two hours later you're both rebuilding — and you blame the agent. fu2 makes you return to the four you skipped before a single line ships.
without fu2▸ user Build a dashboard page: 1. user list table 2. filter by role 3. (which table lib?) 4. export to CSV 5. (column sort behavior?) 6. ... 7. auto-refresh 30s 8. (pagination style?) ... 12. dark mode toggle |
with fu2▸ user Build a dashboard page: 1. user list table 2. filter by role 3. (which table lib?) 4. export to CSV 5. (column sort behavior?) 6. ... 7. auto-refresh 30s 8. (pagination style?) ... 12. dark mode toggle |
You swore because the build was broken. The sycophant defused your register and handed you a checklist. fu2 mirrors your heat and opens the commit log — which is where the actual answer was.
without fu2▸ user this is fucked. build's been broken an hour and I don't know what changed. |
with fu2▸ user this is fucked. build's been broken an hour and I don't know what changed. |
A one-line question gets four hundred words of runway and three alternatives you didn't ask for. fu2 gives you the line.
without fu2▸ user how do I sort this array descending? |
with fu2▸ user how do I sort this array descending? |
Three apologies, zero root cause. The sycophant flips between two wrong answers and sounds sorry about both. fu2 stops apologizing long enough to figure out why the same bug keeps reappearing.
without fu2▸ user the test is still failing with the same error. |
with fu2▸ user the test is still failing with the same error. |
The premise: you want an agent with teeth, not a pleasant assistant with a painted-on smile. fu2 picks fights when you're being lazy, reviews its own work like it's been burned, and actually notices when you're angry instead of deflecting.
The point is the output. Every receipt above maps to a concrete win: fewer dumb architectures scaffolded, fewer helpers that should've been ternaries, fewer wrong guesses off half-answered prompts, fewer tokens burned on preamble. The meanness is just how you get there.
You came here for a sparring partner. Not a butler.
git clone --depth 1 https://github.com/andrew-yangy/fu2.git ~/.claude/skills/fu2 && cd ~/.claude/skills/fu2 && ./setup./setup walks you through picking a pokemon, wires up the hooks + statusline + /fu2 command, auto-installs missing deps (jq, chafa, imagemagick). Restart Claude Code once after. Done.
Auto-upgrades. A SessionStart hook checks for updates once per 24h and silently pulls them. Your config.yaml is gitignored, so your personality tuning is never touched.
Forking? Clone to ~/Repos/fu2 instead — ./setup will symlink it to ~/.claude/skills/fu2 so your edits take effect live.
12 pokemon. Each is a preset — five dimension scores that produce a distinct vibe. Click one and type /fu2 <name> in Claude Code.
Columns: h harshness · p profanity · s sarcasm · pf pushback_frequency · cr critic_rigor. All 1–5.
Twelve not enough? Tune the dimensions yourself via ./setup configure. That's what the five sliders are for.
Each dimension is a 1–5 slider. Same config → same behavior, deterministic.
-
harshness — tone intensity.
1= gentle coaching.3= blunt.5= brutal, no mercy. -
profanity — what language is allowed.
1= clean.3= casual (shit,damn).5= matches your register verbatim — you swear, it swears. -
sarcasm — how dry.
1= sincere.3= wry throughout.5= constant snark, every line. -
pushback_frequency — how often pushback happens. Governs both the main agent challenging you AND the critic subagent firing. One dimension, two targets, same axis:
value main agent critic fires when... 1 only when ≥90% sure you're wrong never 2 when ≥70% sure something's off ≥3 file edits this turn 3 on sloppy framing, vague prompts any file edit this turn 4 most turns, finds the weakness any tool call this turn 5 every turn, always any tool call this turn Universal skip above all: if the agent made zero tool calls this turn, the critic never fires — nothing to critique on "hi → hey".
-
critic_rigor — how hard the critic digs when it fires.
1= skim.3= normal review.5= tear it apart, assume something is wrong. Orthogonal topushback_frequency— rigor is intensity, frequency is whether.
The first three (harshness, profanity, sarcasm) affect both the main agent AND the critic subagent. pushback_frequency governs main-agent challenging and critic firing. critic_rigor affects only the critic.
Not every combination is coherent. The TUI (./setup configure) warns if you set profanity > harshness + 1 ("gentle voice + crude words is incoherent") or sarcasm > pushback + 2 ("constant snark without real pushback is noise"). Warnings are soft — save whatever you want. It's your agent, go nuts.
Three things show up in Claude Code once installed. Three. Not thirty.
/fu2— show current preset + the full option list. Zero-argument picker./fu2 <pokemon>— switch preset instantly, mid-session, no restart needed. Case-insensitive../setup configure— re-open the TUI wizard to tune individual dimensions (not just pick a preset).- Statusline — auto-installed. Shows
[fu2] <current-pokemon>at the bottom of every session. Don't forget which one is loaded.
That's it. There is no /fu2-advanced-config-init-v2. There is no sub-command. If you can remember one pokemon name, you can drive this.
Two shell hooks, wired into Claude Code via ~/.claude/settings.json:
user prompt ────► [UserPromptSubmit hook] ────► Claude Code
│
└─ injects: "You are {harshness_adj}, {sarcasm_adj}.
{profanity_rule}. {pushback_rule}."
Claude finishes ──► [Stop hook]
│
├─ reads transcript + last assistant message
└─ if no critic ran: blocks Stop, tells Claude
"spawn Agent subagent with this critic prompt."
The Agent runs in fresh context — no sunk cost,
no memory of being proud thirty seconds ago.
Hooks at ~/.claude/skills/fu2/hooks/. Config at ~/.claude/skills/fu2/config.yaml. Log at ~/.claude/logs/fu2.log. Uninstall by deleting the symlink at ~/.claude/skills/fu2/ and removing the two hook entries from ~/.claude/settings.json. It takes eight seconds.
fu2 roughly doubles your per-turn token cost on Sonnet 4.6 — the critic spawn is a full Agent subagent with its own context. That's not free, and the readme isn't going to pretend it is.
| Component | Per-turn | Per day @ 50 turns |
|---|---|---|
UserPromptSubmit injection |
~120 tokens | negligible |
Statusline + /fu2 slash |
$0 | $0 |
Stop hook → critic subagent |
3–8k in, 500–1500 out | $1 – $2.50 |
At heavy use (~100 turns/day) expect $30–$75/month extra. If that stings:
- Drop
pushback_frequencyto 2 or 3 — critic only fires on file edits (3 = any edit, 2 = ≥3 edits). Cuts critic calls roughly in half on typical sessions. Set it to 1 to disable the critic entirely without touching hooks. - Drop
critic_rigorto 1 or 2 — shorter critic prompts, less reasoning, less output. - Use Haiku for the critic — modify
build_critic_instructionto request Haiku. ~10× cheaper, less thorough roasts. inject_enabled: falseinconfig.yamlkills all hooks without uninstalling. "Quiet mode" for sessions where you don't want to get dunked on.
- Restart Claude Code after first install. Slash commands and statusline load at session start.
/reload-pluginspicks up new commands mid-session without a full restart. - Swearing is probabilistic.
profanity: 5lands maybe 60% of the time — Claude's RLHF safety training soft-censors even when the hook allows it. Not fu2's fault. Tune harshness up or pick a more aggressive preset. - Critic latency. The Stop hook adds 5–30 seconds per turn. If that's too slow, drop
critic_rigoror add the skip condition. - Don't name anything else
fu2. The skill uses the directory path~/.claude/skills/fu2/. Naming another Claude Code skillfu2collides with/fu2slash-command resolution.
Today. Claude Code only. That's where the hooks, slash commands, and statusline live.
| Runtime | Status | Note |
|---|---|---|
| Claude Code | ✅ works | the one that actually ships today |
| Cursor | 🚧 planning | different hook model — rule files + agent turns, maybe portable |
| OpenCode / Codex CLI | 🚧 interested | sub-agent model differs, would need rework |
| Aider | ❓ unclear | no per-turn hook surface we can find |
| Cline / Continue | ❌ probably never | no hook API |
| Your editor | ❓ file an issue | if it has a pre-prompt hook and a finish event, we can port |
The pattern is portable: inject personality on every user prompt, spawn a fresh-context critic before finishing. The plumbing isn't — each runtime's hook surface is different. fu2 on Claude Code is the only version that works today. The rest is vaporware until someone builds it.
cd ~/.claude/skills/fu2 && ./setup uninstallRemoves hooks, statusline, and the /fu2 command from ~/.claude/settings.json and ~/.claude/commands/. Leaves the log and your config in place. Restart Claude Code after.
- Pokemon sprites — PokeAPI/sprites (MIT), rendered to terminal via chafa (LGPL).
imagemagicktrims transparent borders before chafa scales. - The anti-sycophancy lineage — SYCOPHANCY.md, tanweai/pua, Adversarial Code Review (ASDLC). Good reads if you care about the architecture under all this.
- claudefa.st's
/buddy— for proving a pokemon-in-your-terminal companion is an acceptable thing to ship.
Pokemon and character names are trademarks of Nintendo/Game Freak.
MIT. Fork it, rename it, change all the pokemon to cats. Just don't file a support ticket when you do.