Skip to content

Hooks

Install hooks with ff hook so your shell or agent client attempts snapshots as you work. Choose the clients you use on this machine:

Install

ff hook bash             # Shell alias and prompt snapshots
ff hook claude           # Claude Code hooks and skill
ff hook -l               # List installed configuration

Hook installation changes local files and makes no network request.

Activate

Restart the shell or source the file named by the installer; each shell page gives the exact command. Restart Claude Code after installing its plugin. For Codex, the installer runs codex plugin add fufu@fufu when codex is on PATH and names the command otherwise; then run /hooks and review and approve the hook by hash after installation or changes. Copilot CLI loads the plugin live on its next session. Cursor discovers its user-local plugin on a new session in a trusted workspace. Restart OpenCode or Qwen Code before testing their new configuration.

Cursor cloud agents get no user-local hooks, so nothing captures there. Cursor has no turn-end capture event — its CLI gates stop on user settings — so a final edit there waits for sessionEnd or the next repository command; Codex and Qwen Code install Stop and SessionEnd, and Copilot CLI agentStop and sessionEnd. See agent setup for each client's events and replies.

Verify

Run ff hook -l and ff doctor --no-fetch. They inspect installed files, not a running shell, loaded plugin, or Codex trust approval. Use the checks on each shell page or the agent capture-and-recovery check to verify actual events.

Shell hooks add a git alias or function that routes through ff git, plus a prompt hook running ff trigger shell. Allowed passthrough commands attempt a snapshot before Git runs; strict-policy refusals happen before that capture. Prompt snapshots are quiet. Recovery still depends on a successful retained snapshot; coverage and limits apply.

Files changed

  • Shells: marked lines in the shell's startup file. Alias and prompt hook are managed independently. Recognized hand-written equivalents are reported and left alone; the missing piece can still be installed.
  • Agent settings: fufu merges recognized hook commands into JSON. Unrelated settings and commands survive, although formatting can change. Invalid JSON is refused without rewriting that file. A command matching fufu's current or retired spelling is treated as managed even if you pasted it by hand.
  • Owned directories: the Claude Code, Codex, and Cursor plugin directories are written and removed as fufu-managed content, the skill inside each; OpenCode gets one plugin file and a skill directory under its config directory, and a fufu.js fufu did not write is reported and left alone. Keep personal files elsewhere. Codex also merges one entry into ~/.agents/plugins/marketplace.json, and Copilot CLI one into ~/.agents/plugins/copilot/marketplace.json plus a registration in ~/.copilot/settings.json; those files follow the agent-settings rules above. Qwen Code receives no skill from this installer.

Re-running an installer repairs missing or stale managed entries and refreshes shipped content. ff hook -u refreshes already installed integrations without adding new clients.

Remove

ff unhook bash
ff unhook claude

ff unhook removes managed lines, entries, and owned directories for the named client. Unrelated settings and hand-written shell hooks survive. Restart the shell or client afterward: removing configuration does not unload it from an existing process.

Troubleshooting and migration

ff doctor --fix repairs partial or stale managed hooks and stale skills. Activation and trust remain separate steps. If snapshots are absent, check the running shell/client and the verification recipe before relying on an installed-file row.

Retired shell markers and trigger spellings are recognized and upgraded by the installer. Managed MCP registrations from before v0.15 are removed by ff hook <client> or ff hook -u (and by ff unhook cursor); unrelated MCP commands and unmarked Codex TOML entries survive. ff hook codex also strips the entries and skill an earlier fufu wrote under ~/.codex/, and ff hook cursor the entries it merged into ~/.cursor/hooks.json. Gemini CLI is no longer a slug: ~/.gemini is never touched, and entries there keep capturing through the retired ff trigger gemini source. Client pages identify the affected files.