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

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.
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
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.
| Skill | When to use |
|---|---|
file-pr | File or update a concise pull request |
babysit-pr | Monitor a PR through review bots and CI |
arena | Run competing attempts, then graft the strongest ideas into one result |
bro | Restate the last message in plain language |
verify | Prove a behavior change on the user surface with revision-bound evidence |
review | Filter adversarial findings by reachable failure and concrete evidence |
Claude Code mods: plugins of function hooks that change how Claude Code looks and behaves. They are Claude Code only.
| Mod | What it does |
|---|---|
glamour-dark | Draws replies as rich markdown in glamour's dark style, one sentence per line |
marathon-footer | Restyles the hints after the mode label under the prompt to match the SLOPOTHON banner: ⏵⏵ auto mode on · ⇧⇥ CYCLE // ← 1 AGENT |
redact-secrets | Swaps secrets for placeholders before Claude reads them or the session logs them; Write and Edit put the real values back |
tool-lines | Draws each tool call as one compact line and hides its result block |
ascii-spinner | Swaps the working line (verb, timer, tokens, effort, tip) for a one-row WEAVEworm rethreading synthsilk, in Sekiguchi colors |
slopothon | Paints 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.
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.
skills/<name>/SKILL.md with required name and description frontmatter.name matching the directory. Lowercase, hyphens only.references/; keep SKILL.md short enough to load on activation.See agentskills.io/specification.
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.
hooks/register.ts 52 lines1import 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