cd /news/ai-agents/i-used-claude-code-s-hooks-to-pause-… · home › topics › ai-agents › article
[ARTICLE · art-161940] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

I used Claude Code's hooks to pause a terminal game the moment my agent finishes

A developer built Agent Arcade, a set of terminal games that pause and display a banner the moment a coding agent finishes its turn or requests permission, using Claude Code hooks that write a single word to a signal file (~/.agent-arcade/signal) which the game polls via its modified timestamp. The developer notes that the PermissionRequest hook should be used instead of Notification for "agent needs you" alerts, since the permission-prompt notification only fires after roughly six seconds of inactivity, and the tool is now distributed as a Claude Code plugin that registers an immediate /arcade command without editing settings.json.

by read4 min views6 publishedNov 1, 2026

Claude Code and Codex often take a few minutes on a task. In that time I either stare at the spinner, or switch to another tab and forget to come back for ten minutes.

So I built Agent Arcade: tiny terminal games to play during the wait. The useful part isn't the game. It's that the game s and tells you the moment your agent is done or needs you, so the break never runs long.

This post is about how that works, because the same trick (an agent hook that writes a file, something else that watches it) is handy for a lot more than games.

Claude Code can run a command at certain moments of a session. Three of those moments matter here:

Hook Fires when Agent Arcade says
Stop Claude finishes its turn "done"
PermissionRequest Claude shows a permission prompt "ask"
Notification other "waiting for you" moments, like an idle prompt "ask"

Each hook runs one tiny command, agent-arcade notify or agent-arcade notify ask. All it does is write a word to a file:

// bin/agent-arcade.mjs
else if (cmd === 'notify') {
  fs.mkdirSync(DIR, { recursive: true });
  fs.writeFileSync(SIGNAL, arg === 'ask' ? 'ask\n' : 'done\n'); // ~/.agent-arcade/signal
}

No server, no socket, no daemon. The game, running in another terminal, checks that file's modified time on every tick. A new time means a new event:

// src/shell.mjs
const stamp = () => { try { return fs.statSync(SIGNAL).mtimeMs; } catch { return 0; } };
let seen = stamp();

function checkAgent() {
  const t = stamp();
  if (t === seen) return;          // nothing new
  seen = t;
  let kind = 'done';
  try { kind = fs.readFileSync(SIGNAL, 'utf8').trim() === 'ask' ? 'ask' : 'done'; } catch {}
  agent = kind;                    // shows the banner and s the game
  out.write('\x07');               // terminal bell
}

Using the file's modified time instead of its contents means two "done" events in a row still count as two events, and a game started after an event doesn't react to an old one.

The same file works for Codex, whose notify setting runs a program after each turn. Any agent that can run a command when it finishes can use it.

My first version used Notification for "Claude needs you". On my Show HN post, a commenter pointed out something I'd missed in the docs: the permission-prompt notification only fires after you haven't typed for about six seconds. Mid-game, you're pressing keys constantly, so the "Claude is waiting" banner could arrive late.

PermissionRequest fires as soon as the prompt appears. The fix was one line in the setup, and the plugin now listens to it directly. The hook never answers the prompt: it only writes "ask", and you approve or deny as usual.

If you write hooks for "the agent needs me" alerts, use PermissionRequest, not Notification.

Two small things make the feel right:

\x1b[?1004h). When you click away, the terminal sends \x1b[O and the game s. When you come back, it sends \x1b[I. Keys typed in the first moment after a banner appears are ignored, because they were meant for the game, not the banner.

This was the fiddly part. /arcade tries, in order:

tmux display-popup -E -w 70% -h 70% agent-arcade, a floating window over your session agent-arcade At first, setup was npm install -g agent-arcade and then agent-arcade setup, which edits ~/.claude/settings.json. That's two steps and a settings file edit.

Now it's a Claude Code plugin, installed from the GitHub repo, which doubles as a plugin marketplace:

/plugin install agent-arcade --marketplace Kuldeep-045/agent-arcade

The plugin registers /arcade as an immediate command, so it runs without a model turn. It opens the game instantly, even while Claude is in the middle of a task, and doesn't add anything to the conversation. It also listens to the same hook events, so there's no settings file to edit:

on('classic.Stop', async ($, e, next) => {
  arcade($, ['notify'], 5000).catch(() => {})       // fire and forget
  return next(e)                                    // never change what Claude does
})

on('classic.PermissionRequest', async ($, e, next) => {
  arcade($, ['notify', 'ask'], 5000).catch(() => {})
  return next(e)
})

The repo only needs two extra files to be installable: the plugin's manifest and a .claude-plugin/marketplace.json listing it. If agent-arcade isn't installed globally, the plugin falls back to npx.

Each game is a plain object: start, tick, key, draw, score. The shell handles the screen, input, pausing, banners and best scores. Snake is about 60 lines. If you have a favourite game for a two-minute wait, I'd love a pull request.

/plugin install agent-arcade --marketplace Kuldeep-045/agent-arcade, then /arcade npm install -g agent-arcade, then agent-arcade setup Code (MIT, no dependencies, no tracking): https://github.com/Kuldeep-045/agent-arcade

What game would you want next?

── more in #ai-agents 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-used-claude-code-s…] indexed:0 read:4min 2026-11-01 · —