SLOPSHOPPER

reflect

Spots hard rules and preferences in your prompts and offers to save them to memory, CLAUDE.md or your second brain.

newtoastpromptmodelprocess
v0.1.0no licenseupdated 2026-10-25ikentrock/starwars-claude-mods/reflect
A shopper browsing a rack in a slop shop
README

starwars-claude-mods

Nine local Claude Code mods (UI and hook plugins) with a light Star Wars flavor.

ModWhat it does
brain-dumpIntercepts long, unstructured prompts, asks clarifying questions, rewrites them into a structured prompt. !raw prefix skips it.
helper-deskProgress bar from the to-do list, plus a side panel for sub-agents (/helper-desk).
cache-clockPrompt-cache countdown, Keep Warm button, /keep-warm.
handoffGenerates a handoff prompt at 250k tokens, on cold cache, or on /handoff.
reflectOffers to save rules/preferences to memory, CLAUDE.md, or a second brain.
chat-inventoryZero-token "In This Chat" panel (/inventory).
switchboard/mods panel to toggle mods and hide panels.
power-cellsGauges above the prompt for context, the 5-hour limit, and a weekly pacing plan: a daily ration, work-day weighting, over/under-plan warnings. /power plan shows the week.
droid-consoleRestyles the whole UI as a droid console: personality palettes, transmission headers, droid spinner words, status band. /droid switches personality.

Status: experimental. They pass claude plugin validate and tsc, but have not been tested at runtime. Expect rough edges.

Install

Add the marketplace once, then install the mods you want (user scope makes them load in every session):

claude plugin marketplace add ikentrock/starwars-claude-mods
claude plugin install brain-dump@starwars-claude-mods --scope user
claude plugin install cache-clock@starwars-claude-mods --scope user
claude plugin install chat-inventory@starwars-claude-mods --scope user
claude plugin install droid-console@starwars-claude-mods --scope user
claude plugin install handoff@starwars-claude-mods --scope user
claude plugin install helper-desk@starwars-claude-mods --scope user
claude plugin install power-cells@starwars-claude-mods --scope user
claude plugin install reflect@starwars-claude-mods --scope user
claude plugin install switchboard@starwars-claude-mods --scope user

Or one at a time from a session prompt:

/plugin install <mod> --marketplace ikentrock/starwars-claude-mods

Update later with claude plugin marketplace update starwars-claude-mods.

Source 1 files
hooks/register.tsx 85 lines
1import type { EngineInterface, Register } from 'claude-code'
2
3const MODEL = 'haiku'
4const HINT =
5  /\b(always|never|don'?t|do not|stop (doing|using)|from now on|going forward|make sure|i prefer|i like (it )?when|i want you to|must|should always|should never|rule)\b/i
6
7const CHOICES = ['Built-in memory', 'CLAUDE.md', 'Second brain', 'Not now'] as const
8
9const EXTRACT = (text: string) => `A user sent this message to a coding assistant:
10
11<message>
12${text}
13</message>
14
15Did the user state a hard rule or lasting preference for how the assistant should work (not a one-off instruction for this task)? If yes, output the rule as one short imperative sentence. If not, output exactly: NONE`
16
17const slug = (text: string) =>
18  text
19    .toLowerCase()
20    .replace(/[^a-z0-9]+/g, '-')
21    .replace(/^-|-$/g, '')
22    .slice(0, 40) || 'rule'
23
24async function append($: EngineInterface, path: string, line: string) {
25  const dir = path.slice(0, path.lastIndexOf('/'))
26  await $.process.run(['mkdir', '-p', dir])
27  const before = (await $.fs.exists(path)) ? await $.fs.read(path) : ''
28  const gap = before === '' || before.endsWith('\n') ? '' : '\n'
29  await $.fs.write(path, `${before}${gap}${line}\n`)
30}
31
32export const register: Register = (on, options) => {
33  let pending: string | undefined
34
35  on('prompt.submit', async ($, e, next) => {
36    if (!e.command && !e.isMeta && HINT.test(e.text)) {
37      const found = await $.model.complete({
38        model: MODEL,
39        prompt: EXTRACT(e.text.slice(0, 4000)),
40        maxTokens: 120,
41        effort: 'low',
42      })
43      const rule = found.isAnswered ? found.text.trim() : 'NONE'
44      pending = rule === 'NONE' || rule === '' ? undefined : rule
45    }
46
47    return next(e)
48  })
49
50  // Ask once the turn is over so the popup never fights a permission dialog.
51  on('turn.complete', async ($, e, next) => {
52    const rule = pending
53    if (rule === undefined || e.agentId !== undefined) return next(e)
54    pending = undefined
55
56    const choice = await $.ui.ask(`Reflect: a rule, I sense. Save it? "${rule}"`, {
57      options: [...CHOICES],
58      header: 'Reflect',
59    })
60    const home = (await $.env.get('HOME')) ?? ''
61    const cwd = await $.session.cwd()
62
63    if (choice === 'Built-in memory') {
64      const dir = `${home}/.claude/projects/${cwd.replace(/[/.]/g, '-')}/memory`
65      const name = `feedback-${slug(rule)}`
66      await $.process.run(['mkdir', '-p', dir])
67      await $.fs.write(
68        `${dir}/${name}.md`,
69        `---\nname: ${name}\ndescription: ${rule.replace(/\n/g, ' ')}\nmetadata:\n  type: feedback\n---\n\n${rule}\n\n**Why:** the user stated it as a standing rule.\n**How to apply:** follow it in every session.\n`,
70      )
71      await append($, `${dir}/MEMORY.md`, `- [${rule.slice(0, 60)}](${name}.md) — user rule`)
72      $.ui.toast('Reflect: saved to built-in memory.')
73    } else if (choice === 'CLAUDE.md') {
74      await append($, `${cwd}/CLAUDE.md`, `- ${rule}`)
75      $.ui.toast('Reflect: added to CLAUDE.md.')
76    } else if (choice === 'Second brain') {
77      const file = String(options.secondBrainFile ?? '~/second-brain/rules.md').replace(/^~/, home)
78      await append($, file, `- ${rule}`)
79      $.ui.toast(`Reflect: saved to ${file}.`)
80    }
81
82    return next(e)
83  })
84}
85