Band above the prompt showing the walk-with-me mode, with buttons for its commands.

Skills for coding agents.
curl -fsSL shalom2552.github.io/agent-skills/install | bash
Or clone and run ./install. See ./install --help for options.
| Skill | Description |
|---|---|
docs-sync | Find and fix drift between docs and code. |
dotconf | Answer, change, and remember dotfile and app configs. |
read-only | Lock the session to read-only; change nothing. |
setup-sh25-skills | Install, manage and wire up shalom2552's agent-skills assets. |
system-audit | Read-only health, security and cleanliness audit of this machine. |
system-fix | Diagnose, fix, and document a system or config fault on this machine. |
to-prompt | Write a handoff prompt for a fresh agent. |
walk-with-me | Learn languages and idioms by coding with a coach. |
scripts/statusline.sh - status line for Claude Code.
Run setup-sh25-skills to wire statusLine.
Claude Code plugins in mods/. ./install mods adds this repo as the shalom2552 marketplace and installs them; without the installer:
/plugin install <mod> --marketplace shalom2552/agent-skills
| Mod | Description |
|---|---|
spinner-words | Swap the spinner verbs for dev ones. |
hooks/register.tsx 79 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4import type { Mode } from '../types'
5
6export const TOOL = 'mcp__walk-with-me__mode'
7
8const mode = atom({ plugin: 'walk-with-me', key: 'mode' } as const, 'off' as Mode)
9
10const set = ($: EngineInterface, next: Mode) => update($, mode, () => next)
11
12const COMMANDS: Record<'coach' | 'interview', string[]> = {
13 coach: ['check', 'show', 'more', 'pause', 'done'],
14 interview: ['run', 'submit', 'hint', 'pause', 'give up'],
15}
16
17const ENDS = ['pause', 'done']
18
19export const register: Register = on => {
20 on('session.start', async ($, e, next) => {
21 await $.tool.register({
22 name: 'mode',
23 description:
24 'Set the /walk-with-me band. "coach" or "interview" once intake picks the mode; "off" when the session pauses or its summary is written.',
25 inputSchema: {
26 type: 'object',
27 properties: { mode: { type: 'string', enum: ['coach', 'interview', 'off'] } },
28 required: ['mode'],
29 },
30 })
31
32 return next(e)
33 })
34
35 on('skill.prompt', { skill: 'walk-with-me' }, async ($, e, next) => {
36 await set($, 'intake')
37
38 return next(e)
39 })
40
41 on('tool.call', { tool: TOOL }, async ($, e) => {
42 const asked = (e as { mode?: unknown }).mode
43 if (asked !== 'coach' && asked !== 'interview' && asked !== 'off') {
44 return { result: 'mode must be "coach", "interview" or "off".' }
45 }
46 await set($, asked)
47
48 return { result: asked === 'off' ? 'Band off.' : `Band: ${asked}.` }
49 })
50
51 on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
52 const current = await read($, mode)
53 if (current === 'off' || e.props.hasSurvey) return next(e)
54
55 const { Box, Button, Text } = $.ui.resolve(e)
56
57 return (
58 <Box gap={1}>
59 <Text bold inverse color="success">
60 {current === 'intake' ? ' WALK ' : ` WALK · ${current.toUpperCase()} `}
61 </Text>
62 {!e.props.isWorking &&
63 current !== 'intake' &&
64 COMMANDS[current].map((cmd, i) => (
65 <Button
66 variant={i === 0 ? 'primary' : undefined}
67 key={cmd}
68 label={cmd[0].toUpperCase() + cmd.slice(1)}
69 onPress={async () => {
70 if (ENDS.includes(cmd)) await set($, 'off')
71 void $.prompt.submit({ text: cmd, asUser: true })
72 }}
73 />
74 ))}
75 </Box>
76 )
77 })
78}
79types/index.d.ts 8 lines1export type Mode = 'off' | 'intake' | 'coach' | 'interview'
2
3declare module 'claude-code' {
4 interface PluginState {
5 'walk-with-me': { mode: Mode }
6 }
7}
8