SLOPSHOPPER

long-task-alert

צליל והודעה כשמשימה ארוכה מסתיימת (ברירת מחדל: 5 דקות ומעלה)

newtoastaudio
v0.1.0no licenseupdated 2026-10-243floors/claude-mods/long-task-alert
A shopper browsing a rack in a slop shop
README

claude-mods

Small mods for Claude Code, made for working in Hebrew.

ModWhat it does
rtl-messagesHebrew and Arabic messages, yours and Claude's, drawn right to left in the terminal. The desktop app already does this by itself, so there the mod stays out of the way.
usage-bandA band above the prompt: how much is left of the 5-hour and weekly limits, context fill and session cost. /usage-band hides or shows it.
long-task-alertA chime and a short message when a task took 5 minutes or more. The minutes are a setting.

Install

In a terminal running Claude Code, install the ones you want:

/plugin install rtl-messages --marketplace 3floors/claude-mods
/plugin install usage-band --marketplace 3floors/claude-mods
/plugin install long-task-alert --marketplace 3floors/claude-mods

In the desktop app: click + next to the prompt box, then Plugins, Add marketplace with 3floors/claude-mods, then Add plugin.

The chime in long-task-alert is an original sound made for this repository, free to use.

Source 3 files
hooks/register.ts 28 lines
1import type { Register } from 'claude-code'
2
3import { message, shouldAlert } from './alert'
4
5const turn = { plugin: 'long-task-alert', key: 'turn' } as const
6
7export const register: Register = (on, options) => {
8  const thresholdMin = Number(options.thresholdMinutes) || 5
9
10  on('turn.start', async ($, e, next) => {
11    await $.state.set(turn, { turnId: e.turnId, at: await $.clock.now() })
12    return next(e)
13  })
14
15  on('turn.complete', async ($, e, next) => {
16    const res = await next(e)
17    if (e.agentId) return res // subagent turns are part of the main one
18    const { value } = await $.state.get(turn)
19    if (!value || value.turnId !== e.turnId) return res
20    const now = await $.clock.now()
21    if (shouldAlert(value.at, now, thresholdMin, e.reason)) {
22      $.ui.toast(message(value.at, now))
23      await $.audio.play({ asset: 'sounds/done.aiff' }).catch(() => {})
24    }
25    return res
26  })
27}
28
hooks/alert.ts 9 lines
1const MIN = 60_000
2
3// aborted = the person interrupted, so they are at the screen: no alert
4export const shouldAlert = (startedAt: number, now: number, thresholdMin: number, reason: string) =>
5  reason !== 'aborted' && now - startedAt >= thresholdMin * MIN
6
7export const message = (startedAt: number, now: number) =>
8  `המשימה הסתיימה אחרי ${Math.round((now - startedAt) / MIN)} דק׳`
9
types/index.d.ts 8 lines
1export type TurnStart = { turnId: string; at: number }
2
3declare module 'claude-code' {
4  interface PluginState {
5    'long-task-alert': { turn: TurnStart | null }
6  }
7}
8