SLOPSHOPPER

disk-alert

Shows a warning band above the prompt when a disk is nearly full.

newbandprocesstimer
v0.1.0MITupdated 2026-10-09AliakbarNateghi/cc-disk-alert
A shopper browsing a rack in a slop shop
README

disk-alert

A Claude Code mod. At session start and every 5 minutes it runs df on your paths and shows a band above the prompt when one is nearly full:

⚠ /mnt/c 91% full (12G free)

Nothing shows when every path is under the threshold.

Install

/plugin install disk-alert --marketplace AliakbarNateghi/cc-disk-alert

Options

  • paths: comma-separated paths to check (default /,/mnt/c, for WSL2)
  • threshold: percent used that triggers the warning (default 85)
Source 3 files
hooks/register.tsx 49 lines
1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register, Timer } from 'claude-code'
3
4import { diskAlerts } from './df'
5
6const alerts = atom({ plugin: 'disk-alert', key: 'alerts' } as const, [] as string[])
7const EVERY_MS = 5 * 60_000
8
9async function check($: EngineInterface, paths: string[], threshold: number) {
10  try {
11    // df exits non-zero when one path is missing but still prints the rest.
12    const { stdout } = await $.process.run(['df', '-P', '-h', ...paths])
13    const lines = diskAlerts(stdout, threshold)
14    await update($, alerts, () => lines)
15  } catch {}
16}
17
18export const register: Register = (on, options) => {
19  const threshold = Number(options.threshold ?? 85)
20  const paths = String(options.paths ?? '/,/mnt/c')
21    .split(',')
22    .map(p => p.trim())
23    .filter(Boolean)
24  let timer: Timer | undefined
25
26  on('session.start', async ($, e, next) => {
27    const started = await next(e)
28    timer?.cancel()
29    void check($, paths, threshold)
30    timer = $.clock.every(EVERY_MS, () => void check($, paths, threshold))
31    return started
32  })
33
34  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
35    const lines = await read($, alerts)
36    if (lines.length === 0) return next(e)
37    const { Box, Text } = $.ui.resolve(e)
38    return (
39      <Box flexDirection="column">
40        {lines.map(l => (
41          <Text key={l} color="warning">
42            {l}
43          </Text>
44        ))}
45      </Box>
46    )
47  })
48}
49
hooks/df.ts 13 lines
1// Parses `df -P -h` output into one warning line per mount at or above threshold.
2export function diskAlerts(stdout: string, threshold: number): string[] {
3  const alerts: string[] = []
4  for (const line of stdout.trim().split('\n').slice(1)) {
5    const [, , , avail, use, ...mount] = line.trim().split(/\s+/)
6    const pct = parseInt(use ?? '', 10)
7    if (!Number.isNaN(pct) && pct >= threshold) {
8      alerts.push(`⚠ ${mount.join(' ')} ${pct}% full (${avail} free)`)
9    }
10  }
11  return alerts
12}
13
types/index.d.ts 8 lines
1export type DiskAlerts = string[]
2
3declare module 'claude-code' {
4  interface PluginState {
5    'disk-alert': { alerts: DiskAlerts }
6  }
7}
8