SLOPSHOPPER

marathon-footer

Restyles the hints after the mode label under the prompt to match the SLOPOTHON banner: '⇧⇥ CYCLE // ← 1 AGENT'

newspinner
v0.1.0MITupdated 2026-10-09binbandit/bin-stack/mods/marathon-footer
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · marathon-footer
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? SHORTCUTS

Draws

Prompt hint
? SHORTCUTS
README

bin-stack

A harness-agnostic agent skill stack.

Skills follow the Agent Skills format (SKILL.md + optional scripts/references/assets). One source of truth under skills/. Works with Cursor, Claude Code, Codex, and any other agent that discovers skills the standard way.

Inspired by stacks like pstack, but not locked to a single product.

Install

Via skills CLI

npx skills add binbandit/bin-stack

Pick specific skills:

npx skills add binbandit/bin-stack --skill file-pr --skill babysit-pr --skill arena --skill bro

Symlink a clone (one copy, every harness)

git clone https://github.com/binbandit/bin-stack.git ~/Developer/ai/bin-stack
cd ~/Developer/ai/bin-stack
./scripts/link-skills.sh

That links each skill directory into the harness roots you already have (~/.agents/skills, ~/.cursor/skills, ~/.claude/skills, ~/.codex/skills, …). Edit here; every harness sees the same files.

Skills

SkillWhen to use
file-prFile or update a concise pull request
babysit-prMonitor a PR through review bots and CI
arenaRun competing attempts, then graft the strongest ideas into one result
broRestate the last message in plain language
verifyProve a behavior change on the user surface with revision-bound evidence
reviewFilter adversarial findings by reachable failure and concrete evidence

Mods

Claude Code mods: plugins of function hooks that change how Claude Code looks and behaves. They are Claude Code only.

ModWhat it does
glamour-darkDraws replies as rich markdown in glamour's dark style, one sentence per line
marathon-footerRestyles the hints after the mode label under the prompt to match the SLOPOTHON banner: ⏵⏵ auto mode on · ⇧⇥ CYCLE // ← 1 AGENT
redact-secretsSwaps secrets for placeholders before Claude reads them or the session logs them; Write and Edit put the real values back
tool-linesDraws each tool call as one compact line and hides its result block
ascii-spinnerSwaps the working line (verb, timer, tokens, effort, tip) for a one-row WEAVEworm rethreading synthsilk, in Sekiguchi colors
slopothonPaints a SLOPOTHON lockup over the Claude logo in Marathon's design language: block wordmark, a dot-matrix card naming the model and branch, and a livery strip with a tagline and barcode per session. Fullscreen ("tui": "fullscreen") only; it starts each session with a /slopothon row and the logo shows for ~130ms first. Type /slopothon to redraw it inline

Install every mod at user scope:

./scripts/install-mods.sh

The script adds mods/ as the bin-stack marketplace and installs each mod from it. Claude Code reads the mods in place from this clone, so an edit here applies on the next session or /reload-plugins. Re-run it after adding a mod.

Layout

skills/
  file-pr/SKILL.md
  babysit-pr/SKILL.md
  arena/SKILL.md
  bro/SKILL.md
  verify/SKILL.md
  review/SKILL.md
mods/
  .claude-plugin/marketplace.json
  glamour-dark/
  marathon-footer/
  redact-secrets/
  tool-lines/
  ascii-spinner/
  slopothon/
scripts/
  link-skills.sh   # optional: symlink into local harness skill roots
  install-mods.sh  # install the Claude Code mods

Canonical skills live in skills/. Harness-specific paths are adapters (symlinks or CLI installs), not forks of the content.

Authoring

  1. Add skills/<name>/SKILL.md with required name and description frontmatter.
  2. Keep name matching the directory. Lowercase, hyphens only.
  3. Put long reference material in references/; keep SKILL.md short enough to load on activation.
  4. Prefer harness-neutral wording. Call out Cursor / Claude / Codex only when a step truly differs.

See agentskills.io/specification.

License

MIT

The verify and review skills adapt selected pstack guidance by Lauren Tan at revision 9f451cf875ad1239912762f67741e8e5ba6ac0f1. Each skill bundles its provenance and the original MIT notice in LICENSE-pstack so attribution travels with individual skill installs.

Source 1 files
hooks/register.ts 52 lines
1import type { Register } from 'claude-code'
2
3type Hint = { key: string; action: string }
4
5const VOLT = '#C8FF00'
6const SEPARATOR = '  //  '
7
8const CARRIED_MODE_LABEL = /^(?:[\w']+ )+on(?: · | (?=\()|$)/
9const KEYED_HINT = /^\(?([^\s()]+) (?:to|for) ([^()]+?)\)?$/
10const ARROW_HINT = /^([←→↑↓]) (.+)$/
11
12const KEY_GLYPHS: Record<string, string> = {
13  shift: '⇧',
14  tab: '⇥',
15  ctrl: '⌃',
16  opt: '⌥',
17  alt: '⌥',
18  cmd: '⌘',
19  enter: '⏎',
20  return: '⏎',
21}
22
23const glyphsOf = (key: string) =>
24  key
25    .split('+')
26    .map(part => KEY_GLYPHS[part.toLowerCase()] ?? part.toUpperCase())
27    .join('')
28
29function hintOf(part: string): Hint | undefined {
30  const [, key, action] = KEYED_HINT.exec(part) ?? ARROW_HINT.exec(part) ?? []
31  return key === undefined || action === undefined ? undefined : { key, action }
32}
33
34const isHint = (hint: Hint | undefined): hint is Hint => hint !== undefined
35
36export const register: Register = on => {
37  on('ui.render', { component: 'PromptHint' }, ($, e, next) => {
38    if (e.surface !== 'terminal') return next(e)
39    const hints = e.props.hint.replace(CARRIED_MODE_LABEL, '').split(' · ').filter(part => part !== '').map(hintOf)
40    if (hints.length === 0 || !hints.every(isHint)) return next(e)
41    const { Text } = $.ui.resolve(e)
42    return Text({
43      wrap: 'truncate-end',
44      children: hints.flatMap(({ key, action }, index) => [
45        ...(index === 0 ? [] : [Text({ dimColor: true, children: [SEPARATOR] })]),
46        Text({ color: VOLT, bold: true, children: [glyphsOf(key)] }),
47        Text({ dimColor: true, children: [` ${action.toUpperCase()}`] }),
48      ]),
49    })
50  })
51}
52